我问了一个类似的问题,但经过更多的研究,我发现了一些我无法理解的东西,希望有人可以解释导致这种行为的原因:
// We wish to store a integral type, in this case 2 bytes long.
signed short Short = -390;
// In this case, signed short is required to be 2 bytes:
assert(sizeof(Short) == 2);
cout << "Short: " << Short << endl; // output: -390
signed long long Long = Short;
// in this case, signed long long is required to be 8 bytes long
assert(sizeof(Long) == 8);
cout << "Long: " << Long << endl; // output: -390
// enough bytes to store the signed short:
unsigned char Bytes[sizeof(Short)];
// Store Long in the byte array:
for (unsigned int i = 0; i < sizeof(Short); ++i)
Bytes[i] = (Long >> (i * 8)) & 0xff;
// Read the value from the byte array:
signed long long Long2 = (Bytes[0] << 0) + (Bytes[1] << 8);
cout << Long2 << endl; // output: 65146
signed short Short2 = static_cast<signed short>(Long2);
cout << Short2 << endl; // output: -390
输出:
-390
-390
65146
-390
有人可以解释这里发生了什么吗?这是未定义的行为吗?为什么呢?
答案 0 :(得分:1)
这与负数的存储方式有关。负数将以二进制格式的1
开头。
signed long long Long = Short;
这会自动为您进行转换。它不仅仅是将一个位分配给另一个,它正在转换导致您的64位值的值,以1
开头,表示为负,其余表示390 in 2s补码(可以& #39;打扰所有比特的工作。)
signed long long Long2 = (Bytes[0] << 0) + (Bytes[1] << 8);
现在你只检索最后两个字节,它只代表390幅度。您的前两个字节将为零,因此它认为它是一个正数。它应该工作为2 ^ 16 - 390,它确实如此。
signed short Short2 = static_cast<signed short>(Long2);
这是一个溢出。 65146不适合有符号的2字节整数,因此最终会填充签名位,使其被解释为负数。没有共同发生,它代表的负数是-390。