内存中的Char数组表示形式

时间:2019-01-04 00:42:14

标签: c++ pointers

我试图在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“

1 个答案:

答案 0 :(得分:4)

x86-64 CPU(像您一样)在最低内存地址中存储多字节整数的最低有效字节。因此,递增与“ abcd”对应的整数会导致递增其最低有效字节,该字节将最先存储在内存中。这将“ a”字符转换为“ b”。像这样的代码的行为在很大程度上取决于CPU对整数和字符串进行编码的方式以及您对代码的期望,必须考虑到这些细节。

要期望字符串“ abce”,您必须做很多假设:

  1. 您必须期望整数占据4个字节。
  2. 您必须期望最低有效字节最后存储。
  3. 您必须期望字符“ e”的编码比字符“ d”的编码多一。
  4. 您必须期望将“ d”递增为“ e”时,将其视为有符号整数递增不会溢出。

其中一些是合理的假设,但有些不是,但是除非您有所有这些假设的合理依据,否则您的期望是没有道理的。

  

这是预期的行为吗?

这是熟悉您平台的人们所期望的。但是通常很容易避免依赖这些假设,因此最好的建议是不要依赖这些假设。在所有现代平台上,假设3都是不可避免和合理的。