我不能说我知道 C/C++ 不好,但我遇到过有趣的语法。我有这个代码:
int i=7;
char* m=(char*)&i;
m[2]=9;
cout<<i;
它的输出为 589831。所以有人可以详细解释一下这里发生了什么。
我不能说我知道 C/C++ 不好,但我遇到过有趣的语法。我有这个代码:
int i=7;
char* m=(char*)&i;
m[2]=9;
cout<<i;
它的输出为 589831。所以有人可以详细解释一下这里发生了什么。
{ 07, 00, 00, 00 }
{ 07, 00, 09, 00 }
长话短说,这是一个如何在多字节整数中操作单个字节的示例。
整数i
很可能占用 4 个字节,以最低值在前(小端序)排列。在内存中,值如下所示:
0x07 0x00 0x00 0x00
您更改了索引 2 处的值,所以现在它看起来像:
0x07 0x00 0x09 0x00
如果您反转字节并将它们重新组合在一起,它们会使十六进制值 0x00090007 与十进制的 589831 相同。
您将整数地址转换为 achar*
然后使用数组表示法对其进行修改。这一步
m[2] = 9;
和指针算术一样
*(m+2) = 9;
也就是说,它正在修改地址为m
+ 2字节的字节。因此,您已更改初始整数值中的字节之一(第 3 个)
这是我对正在发生的事情的细分,然后是解释。
// 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;
由于三个原因,这是一件非常危险和愚蠢的事情......
您不应该指望架构的字节序。您的代码最终可能会在具有不同底层表示形式的 CPU 上运行int
。
你不能指望int
总是 4 个字节。
你现在有一个char*
如果你去对它执行字符串操作可能会导致崩溃。在您的特定情况下,它将打印一个空字符串,但该整数中没有 0 字节并继续读取堆栈的其他部分并不需要太多。
如果你真的,真的,真的需要这样做,首选的方法是使用联合,但这种小玩意很容易出错,联合几乎没有帮助。
int i=7
为整数保留 4 个字节的内存,并且取决于 CPU 架构(假设你的是 i86)会在内存中产生类似的东西
7 0 0 0
然后创建一个指针 m 指向7 0 0 0
. 在m[2] = 9
内存应该看起来像
之后7 0 9 0
(数组从零开始);
然后你打印出我