在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;
}
我的想法是,如果我创建了一个int指针,其值为数组的地址,int类型将使用该地址中的数据字节,然后是可用的下一个3字节数据。在我有限的理解中,我的印象是int和数组都会以相同的方式使用内存:从任意内存地址开始,而不是按顺序使用下一个地址,依此类推。
然而,这个输出并不是我的预期:我得到'A'的ascii值。对我而言似乎表明我的解决方案不正确,我理解如何处理内存是不正确的,或两者兼而有之。
这个小小的黑客怎么可能完成,我在哪里错了?我希望通过更好地理解指针和引用如何工作,以及如何存储和使用内存来远离这一点。
谢谢!
答案 0 :(得分:8)
你正在遇到小端和大端的数字代表。
让我们看看用于表示4字节整数的4-btyes的值。
+----+----+----+----+ | N1 | N2 | N3 | N4 | +----+----+----+----+
在big-endian表示中,这4个字节表示:
N1*2^24 + N2*2^16 + N3*2^8 + N4
在小端表示中,这4个字节表示:
N1 + N2*2^8 + N3*2^16 + N4*2^24
在你的情况下。
N1 = 'A' (65 decimal)
N2 = 0
N3 = 0
N4 = 0
由于您获得的整数值为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;
}
我用上面的代码得到的输出:
1090519040 41000000