我试图在char数组上执行按位运算,就好像它是一个int一样,本质上将字节视为内存中的连续区域。下面的代码说明了我的问题。
char *cstr = new char[5];
std::strcpy(cstr, "abcd");
int *p = (int *)(void *)cstr;
std::cout << *p << " " << p << "\n";
std::cout << cstr << " " << (void *)cstr << "\n";
std::cout << sizeof(*p) << "\n";
(*p)++;
std::cout << *p << " " << p << "\n";
std::cout << cstr << " " << (void *)cstr << "\n";
产生以下输出:
1684234849 0x55f046e7de70
abcd 0x55f046e7de70
4
1684234850 0x55f046e7de70
bbcd 0x55f046e7de70
对代码及其工作原理的快速解释(据我了解):
我用“ abcd”初始化cstr
char *cstr = new char[5];
std::strcpy(cstr, "abcd");
我将p指向cstr的地址,并指定我希望它为int
int *p = (int *)(void *)cstr;
我测试p指向它应该在哪里,并且它占用4个字节
std::cout << *p << " " << p << "\n";
std::cout << cstr << " " << (void *)cstr << "\n";
std::cout << sizeof(*p) << "\n";
然后我将地址p指向的整数递增
(*p)++;
因此,现在,由于“ abcd”是内存中32位的连续块,因此递增1应该会产生“ abce”。而是,代码成功地增加了整数,但将char数组保留为“ bbce”。最后一部分检查整数和cstr的新值
std::cout << *p << " " << p << "\n";
std::cout << cstr << " " << (void *)cstr << "\n"
这是预期的行为吗?
PS:我使用以下命令在Linux机器上编译了代码:g ++ main.cpp -o main。
file main
产生以下输出:“ 1:动态链接的ELF 64位LSB共享对象,x86-64,版本1(SYSV),动态解释,用于GNU的解释器/lib64/ld-linux-x86-64.so.2。 / Linux 3.2.0“
答案 0 :(得分:4)
x86-64 CPU(像您一样)在最低内存地址中存储多字节整数的最低有效字节。因此,递增与“ abcd”对应的整数会导致递增其最低有效字节,该字节将最先存储在内存中。这将“ a”字符转换为“ b”。像这样的代码的行为在很大程度上取决于CPU对整数和字符串进行编码的方式以及您对代码的期望,必须考虑到这些细节。
要期望字符串“ abce”,您必须做很多假设:
其中一些是合理的假设,但有些不是,但是除非您有所有这些假设的合理依据,否则您的期望是没有道理的。
这是预期的行为吗?
这是熟悉您平台的人们所期望的。但是通常很容易避免依赖这些假设,因此最好的建议是不要依赖这些假设。在所有现代平台上,假设3都是不可避免和合理的。