gpt4 book ai didi

c++ - C++ 数组上指针数学的未定义行为

转载 作者:IT老高 更新时间:2023-10-28 21:45:50 26 4
gpt4 key购买 nike

为什么这个程序的输出是4

#include <iostream>

int main()
{
short A[] = {1, 2, 3, 4, 5, 6};
std::cout << *(short*)((char*)A + 7) << std::endl;
return 0;
}

据我了解,在 x86 little endian 系统上,char 有 1 个字节,短 2 个字节,输出应该是 0x0500,因为数组 A 中的数据以十六进制表示:

01 00 02 00 03 00 04 00 05 00 06 00

我们从开头向前移动 7 个字节,然后读取 2 个字节。我错过了什么?

最佳答案

您在这里违反了严格的别名规则。你不能只读到一个对象的一半就假装它是一个完全独立的对象。您不能像这样使用字节偏移来发明假设的对象。当你把程序交给它时,GCC 完全有权做疯狂的事情!比如回到过去并谋杀猫王。

允许您使用 char* 检查和操作构成任意对象的字节。使用该特权:

#include <iostream>
#include <algorithm>

int main()
{
short A[] = {1, 2, 3, 4, 5, 6};

short B;
std::copy(
(char*)A + 7,
(char*)A + 7 + sizeof(short),
(char*)&B
);
std::cout << std::showbase << std::hex << B << std::endl;
}

// Output: 0x500

( live demo )

但你不能只是“编造”原始集合中不存在的对象。

此外,即使您有一个可以被告知忽略此问题的编译器(例如,使用 GCC 的 -fno-strict-aliasing 开关),构成的对象也不正确与任何当前主流架构对齐short 不能合法地生活在内存中的那个奇数位置,所以你不能假装那里有一个。无法解决原始代码行为的不确定性。事实上,如果你通过 GCC 的 -fsanitize=undefined 开关,它会告诉你很多。

我在简化一点。

关于c++ - C++ 数组上指针数学的未定义行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49339571/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com