我问了一个类似的问题,但是经过更多研究,我发现了一些我无法理解的东西,希望有人可以解释造成这种现象的原因:

// 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/

10-11 16:45