-1

我不能说我知道 C/C++ 不好,但我遇到过有趣的语法。我有这个代码:

int i=7;
char* m=(char*)&i;
m[2]=9;
cout<<i;

它的输出为 589831。所以有人可以详细解释一下这里发生了什么。

4

5 回答 5

3
  1. 一个 4 字节的整数用数字 7 填充。
  2. 4 字节整数映射到四个单字节(字符)的数组。在 x86 这样的小端架构上,最低有效字节在数字中排在第一位,因此数组在内存中看起来像这样:{ 07, 00, 00, 00 }
  3. 整数斜杠字节数组的第 3 个字节更改为 9。现在看起来像这样:{ 07, 00, 09, 00 }
  4. 结果整数(十六进制 90007)被写入标准输出(十进制格式:589831)。

长话短说,这是一个如何在多字节整数中操作单个字节的示例。

于 2012-12-02T23:01:02.863 回答
3

整数i很可能占用 4 个字节,以最低值在前(小端序)排列。在内存中,值如下所示:

0x07 0x00 0x00 0x00

您更改了索引 2 处的值,所以现在它看起来像:

0x07 0x00 0x09 0x00

如果您反转字节并将它们重新组合在一起,它们会使十六进制值 0x00090007 与十进制的 589831 相同。

于 2012-12-02T23:06:35.100 回答
1

您将整数地址转换为 achar*然后使用数组表示法对其进行修改。这一步

m[2] = 9;

和指针算术一样

*(m+2) = 9;

也就是说,它正在修改地址为m+ 2字节的字节。因此,您已更改初始整数值中的字节之一(第 3 个)

于 2012-12-02T23:01:13.657 回答
1

这是我对正在发生的事情的细分,然后是解释。

// An integer on the stack, probably 4 bytes big, but we can't say that for sure.
int i=7; // Looks like 0x0000007 in memory. Endianness needs to be considered.

// Treat that integer as a \0 terminated string.
char* m=(char*)&i; // Acts as an empty string since the first byte is a 0, but we can't count on that.

// Set the second byte to 9.
m[2]=9; // Results in i being 0x00090007 (589831 decimal) on whatever architecture you are running. Once again, can't count on it.

// Print the modified integer.
cout<<i;

由于三个原因,这是一件非常危险和愚蠢的事情......

  1. 您不应该指望架构的字节序。您的代码最终可能会在具有不同底层表示形式的 CPU 上运行int

  2. 你不能指望int总是 4 个字节。

  3. 你现在有一个char*如果你去对它执行字符串操作可能会导致崩溃。在您的特定情况下,它将打印一个空字符串,但该整数中没有 0 字节并继续读取堆栈的其他部分并不需要太多。

如果你真的,真的,真的需要这样做,首选的方法是使用联合,但这种小玩意很容易出错,联合几乎没有帮助。

于 2012-12-02T23:17:38.747 回答
0

int i=7为整数保留 4 个字节的内存,并且取决于 CPU 架构(假设你的是 i86)会在内存中产生类似的东西 7 0 0 0

然后创建一个指针 m 指向7 0 0 0. 在m[2] = 9内存应该看起来像 之后7 0 9 0(数组从零开始);

然后你打印出我

于 2012-12-02T23:11:52.700 回答