我问了一个类似的问题,但是经过更多研究,我发现了一些我无法理解的东西,希望有人可以解释造成这种现象的原因:
// 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
有人可以解释这是怎么回事吗?这是未定义的行为吗?为什么?
最佳答案
这与负数的存储方式有关。负数将以其二进制格式的1
开头。
signed long long Long = Short;
这会自动为您进行转换。它不只是将一个位分配给另一个位,还转换了结果,使您的64位值以
1
开头表示负值,其余的以2s补码表示390(不能打扰)工作所有的位)。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。
关于c++ - 如何正确截断整数类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46739406/