将64位Int转换为Char [](并返回)

时间:2015-07-01 19:59:55

标签: c arrays hex endianness

我编程我希望转换一个big-endian数组(我相信,因为我在Mac上,ints将是little-endian)chars(或者更确切地说是uint8_ts)转换为int64_t并返回。这是我的代码:

int64_t CharsToInt(uint8_t* chars) {
    return chars[0] + (chars[1] * 0x100) + (chars[2] * 0x10000) + (chars[3] * 0x1000000) + (chars[4] * 0x100000000) + (chars[5] * 0x10000000000) + (chars[6] * 0x1000000000000) + (chars[7] * 0x100000000000000);
}

void IntToChars(int64_t i, uint8_t* chars) {
    for(int k = 0; k < 8; k++) {
        chars[k] = i >> k*8;
    }
}

int main() {

    int64_t x;

    unsigned char chars[8];

    IntToChars(x, chars);

    for (int k = 0; k < 8; k++) {
        printf("%0x\n", chars[k]);
    }

    // little endian
    int64_t rv = CharsToInt(chars);

    printf("%lld\n", rv);
}

如果x为12,或任何其他零或正数,则代码完全正常,但如果x为负数,则无法正常工作。

x = 12的输出:

c
0
0
0
0
0
0
0
value: 12

x的输出= -12:

f4
ff
ff
ff
ff
ff
ff
ff
value: -4294967308

这似乎与标志的存储和转换方式有关,因为我认为英特尔(我在Mac上)使用2s-compliment而不是普通的旧标志位。但是,我真的不知道如何确定这是否属实,如果是,如何补偿它(最好是以便携方式)。

我知道还有很多其他类似的问题,而且我已经通读了它们(事实上大部分代码来自它们),但我仍然无法让它工作,所以我问自己。

2 个答案:

答案 0 :(得分:1)

你是对的。 Intel 64和IA-32使用带符号数字的2补码表示。见Intel 64 and IA-32 Architectures Software Developer’s Manual第4.2.1节。因此,读取FFFFFFFFFFFFFFF4表示-12是正确的。在2补码表示中,负数由相应的正数表示,反转所有位并加1:

12 = 000000000000000C -> FFFFFFFFFFFFFFF3 -> FFFFFFFFFFFFFFF4 = -12

如果我可以添加某些内容,您还可以通过执行以下操作将您的char数组转换为uint64_t

int64_t CharsToInt(uint8_t* chars) {
    return *(int64_t*)chars;
}

答案 1 :(得分:0)

在搞砸了它之后,这就是我最终的工作(我想)。它实际上避免了必须一起处理字节序和2s-compliment,通过删除符号并在转换后重新应用它,使用C掩码和乘法:

int64_t CharsToInt(uint8_t* chars) {
    // Don't modify argument
    uint8_t tmp;
    tmp = chars[0];
    bool neg = false;
    if (tmp & 0x80) {
        tmp &= 0x7f;
        neg = true;
    }

    int64_t rv = chars[7] + (chars[6] * 0x100) + (chars[5] * 0x10000) + (chars[4] * 0x1000000) + (chars[3] * 0x100000000) + (chars[2] * 0x10000000000) + (chars[1] * 0x1000000000000) + (tmp * 0x100000000000000);

    if (neg) {
        rv *= -1;
    }
    return rv;

}

void IntToChars(int64_t i, uint8_t* chars) {
    int64_t num = i;
    bool neg = false;
    if (i & 0x8000000000000000) {
        neg = true;
        num *= -1;
    }

    chars[0] = num / 0x100000000000000;
    num = num % 0x100000000000000;
    chars[1] = num / 0x1000000000000;
    num = num % 0x1000000000000;
    chars[2] = num / 0x10000000000;
    num = num % 0x10000000000;
    chars[3] = num / 0x100000000;
    num = num % 0x100000000;
    chars[4] = num / 0x1000000;
    num = num % 0x1000000;
    chars[5] = num / 0x10000;
    num = num % 0x10000;
    chars[6] = num / 0x100;
    num = num % 0x100;
    chars[7] = num;

    if (neg) {
        chars[0] += 0x80;
    }
}