首页 > 解决方案 > 内存中的字符数组表示

问题描述

我试图对 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),动态链接,解释器 /lib64/ld-linux-x86-64.so.2,用于 GNU/Linux 3.2 .0"

标签: c++pointers

解决方案


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

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

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

其中一些是合理的假设,而另一些则不是,但是除非您对所有这些假设都有合理的理由,否则您的期望是不合理的。

这是预期的行为吗?

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


推荐阅读