C++ short array 'reversed' when casted to integer
作为C语言的新手,我一直在玩指针。我编写了以下代码以将短数组解释为整数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream>
int main(){
short array[2] = {10, 9};
short* pointer = array;
std::cout << pointer <<":" << *pointer << std::endl;
// 0xffffcbdc: 10
pointer++;
std::cout << pointer <<":" << *pointer << std::endl;
// 0xffffcbde: 9
int* pointer2 = (int*) array;
std::cout << pointer2 <<":" << *pointer2 << std::endl;
// 0xffffcbdc: 589834
} |
为什么整数589 \\'834(0009 000A)而不是655 \\'369(000A 0009)的值?
从打印的指针地址看来,数组在内存中看起来是有序的,为什么要强制转换为整数会改变它呢?
- 查找大端。和小端。
-
"不明行为"警察今天生效了-我不敢发布答案。
-
首先,将您的整数表示为十六进制值是错误的:589'834 == 0x0009'000A和655'369 == 0x000A'0009。尽管您的int-pointer转换是未定义的行为,但您的CPU似乎使用了" Little Endian",这意味着较低的字节存储在较低的存储器地址中。在" Big Endian"中,较高的字节存储在较低的存储器地址中。使用" Little Endian",无填充和16位short int,您的数组在内存中的布局如下:0A 00 0900。使用" Big Endian",则内存看起来像00 0A 00 09。
此行为是未定义的:
1
| int* pointer2 = (int*) array; |
仅当T2的对齐要求与T1的对齐要求相同或更严格时,才允许将指向T1的指针重新解释为指向T2的指针(有关更多详细信息,请参见参考资料)。由于int的对齐要求比short的对齐要求严格,因此指针重新解释无效。
请注意,将指向int的指针重新解释为指向short的指针将是有效的。
注意:由于未定义行为,因此您的程序可以执行任何操作,包括打印不正确的值甚至崩溃。但是,最常见的原因是您的系统在较低的地址存储了较高整数的字节。这是两个常用选项之一:第二个选项是在较高的地址上存储较高的字节。这两个选项称为字节序。有关更多信息,请参见此处。
-
"请注意,将int指针重新解释为short指针是有效的。"我想补充一点,由于严格的别名规则,您可能不尊重指针。
您正在执行的操作是不确定的行为,因为您违反了严格的别名规则。因此,不要理会从中获得的任何输出。
- 如果您了解整数的存储方式,这并不是没有定义的。在源代码级别未定义,但在CPU级别
-
@nicomp在允许编译器对代码执行任何操作的意义上,它是未定义的。如果代码完全产生任何结果,那纯粹是巧合,并且可能在编译器的版本之间甚至在程序调用之间发生变化。
-
如果您假设没有编译器优化发生,并且您的编译器不是故意故意的话,这只是确定性的。根据定义,UB是不确定的。
-
@nicomp关于耐力的任何陈述都是纯粹的推测。可能是这种行为的原因,但这并不是您可以依靠的任何东西。
-
人们需要停止尝试使UB合理化/恢复正常。执行语言无法保证的事情的代码是不好的,这就是它的结尾。无休止地推测它可能会很好,由于X等原因,它会正常工作,这并不有趣。
-
@underscore_d废话。这个问题层出不穷。没有研究领域会只关注积极成果。
-
@underscore_d并不是在猜测是否可以使用这样的代码,这显然不是很好。这是关于了解底层系统的知识。
-
@kalsowerus您的问题不包含任何信息。为此,您不得不问为什么您的特定系统/编译器(您没有提到)为什么会产生此结果。再次:UB停留在UB。
-
@Jodocus显然,OP无法询问为什么他的特定编译器会产生结果,因为它是UB,我们无法讨论。
-
@nicomp你在矛盾自己。