在Zed Shaw的"以艰难的方式学习C"中,练习9(http://c.learncodethehardway.org/book/ex9.html)有一个额外的学分问题我觉得很有趣.他定义了一个4字符数组,并要求读者弄清楚如何将该数组用作4字节整数.
在这一点上,我知道这很危险,我认为答案是这样的:
#include <stdio.h>
int main(int argc, char *argv[])
{
char name[4] = {'A'};
int *name_int;
name_int = &name;
printf("%d", *name_int);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的想法是,如果我创建一个int指针,其值为数组的地址,int类型将使用该地址中的数据字节,然后是可用的下一个3字节数据.在我有限的理解中,我的印象是int和数组都会以相同的方式使用内存:从任意内存地址开始,而不是按顺序使用下一个地址,依此类推.
但是,这个输出并不是我的预期:我得到'A'的ascii值.对我来说,似乎表明我的解决方案是错误的,我理解如何处理内存是不正确的,或两者兼而有之.
怎么能完成这个小小的黑客攻击呢?我哪里出错了?我希望通过更好地理解指针和引用如何工作以及如何存储和使用内存来远离这一点.
谢谢!
你正在遇到little-endian vs big-endian数字表示.
我们来看看用于表示4字节整数的4-btyes的值.
+----+----+----+----+ | N1 | N2 | N3 | N4 | +----+----+----+----+
在big-endian表示中,这4个字节表示:
N1*2^24 + N2*2^16 + N3*2^8 + N4
Run Code Online (Sandbox Code Playgroud)
在小端表示中,这4个字节表示:
N1 + N2*2^8 + N3*2^16 + N4*2^24
Run Code Online (Sandbox Code Playgroud)
在你的情况下.
N1 = 'A' (65 decimal)
N2 = 0
N3 = 0
N4 = 0
Run Code Online (Sandbox Code Playgroud)
由于你得到的整数值是65,你有一个小的字节表示.如果您想将这些数字视为big-endian表示,则可以使用以下内容:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
char nameString[4] = {'A'};
int name = 0;
for ( i = 0; i < 4; ++i )
{
name = (name << 8) + nameString[i];
}
printf("%d\n", name);
printf("%X\n", name);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出与上面的代码:
1090519040 41000000