C++ 如何正确截断整数类型

C++ 如何正确截断整数类型,c++,C++,我问了一个类似的问题,但经过更多的研究,我发现了一些我无法理解的问题,希望有人能解释导致这种行为的原因: // 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 << "Shor

我问了一个类似的问题,但经过更多的研究,我发现了一些我无法理解的问题,希望有人能解释导致这种行为的原因:

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

有人能解释一下这是怎么回事吗?这是未定义的行为吗?为什么?

这与负数的存储方式有关。负数将以二进制格式的1开头

signed long long Long = Short;
这将自动为您进行转换。它不仅仅是从一个位分配到另一个位,它是转换值,得到以1开头的64位值,表示负数,其余表示390英寸2的补码,不必费心计算所有位

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。

正式地说,程序的行为最多是未指定的,也可能是未定义的,因为它依赖于整数的精确表示,这是一个实现细节。实际上,假设典型的2的补码表示,您正在丢失符号扩展:Long2在高阶字节中有零,而Long有零0xFFs@IgorTandetnik我以这种方式存储整数的原因是,我在某个地方读到了这样做的安全方法。我猜那个消息来源不太好?你能详细说明一下如何将整数正确地存储到字节数组中吗?或者我需要定义我自己的格式吗?Long>>8,带有Long负数,是实现定义的行为。好吧,它起作用了-您得到了与开始时相同的短值。得到不同的long值并不奇怪,因为您只存储了八个字节中的两个字节,因此丢失了信息。你为什么要经历长-长-为什么不从短到字节数组,然后直接返回到短?@IgorTandetnik我正试图用尽可能少的字节将任意整数类型保存到数组中。我将其设置为一个模板函数,其中的参数让我计算所需的字节数,因此,当我读取它们时,我知道用于存储它的字节数-因此,当NumBytes==2时,我可以读取尽可能短的字节数,但我想以更一般的方式进行读取。另外,当NumBytes==3时,我不知道如何读取它!这很有道理,谢谢你的解释!
signed short Short2 = static_cast<signed short>(Long2);