我正在对C中的指针进行一些评论,我对我遇到的一些代码感到有些困惑。我正在对qeeksquiz.com/pointers
进行测验以进行审核,我偶然发现了这段代码:
#include<stdio.h>
int main()
{
int a;
char *x;
x = (char *) &a;
a = 512;
x[0] = 1;
x[1] = 2;
printf("%d\n",a);
return 0;
}
当我遇到x = (char *) &a
时,我有点困惑。我知道x是一个包含a的地址的指针,但是当我们分配x[0] = 1
和x[1] = 2;
时,答案在打印时是513.答案说明它取决于我们是什么机器使用,以及little-endian机器如何改变它读取二进制文件的方式。关于我们如何从512到513,我完全感到困惑。我猜这是因为x [0] = 1,但我不是100%肯定。有人可以帮忙解释一下吗?如果我们分配了x[0] = 2
,那么更改的价值是什么?
感谢您的帮助!
答案 0 :(得分:2)
因为x是指向char的指针,它意味着x [0]和x [1]是对单字节数据的引用,所以在你的内存中你有这样的数据:
1 2
但是,在输出期间你试图引用与16/32位相同的数据,所以我们没有2个单字节,而是1个字,它存储在内存中为0x01 0x02,对于小端,它意味着我们应该交换它们,所以我们得到数字0x201,十进制表示法为513
对于big endian,它将是0x102,即十进制的258
答案 1 :(得分:2)
ASCII艺术!
Little endian Big endian
+----+----+----+----+ +----+----+----+----+
a = 0x200: | 00 | 02 | 00 | 00 | | 00 | 00 | 02 | 00 |
+----+----+----+----+ +----+----+----+----+
+----+----+----+----+ +----+----+----+----+
x[0] = 1: | 01 | 02 | 00 | 00 | | 01 | 00 | 02 | 00 |
+----+----+----+----+ +----+----+----+----+
+----+----+----+----+ +----+----+----+----+
x[1] = 2: | 01 | 02 | 00 | 00 | | 01 | 02 | 02 | 00 |
+----+----+----+----+ +----+----+----+----+
result: 1x1 + 2x256 = 513 1x16777216 + 1x65536 + 2x256 + 0x1 = big
答案 2 :(得分:1)
整数由一系列字节组成。但是不同系统中字节的顺序是不同的。例如,考虑数字134480385(二进制= 00001000000001000000001000000001)。在一个小端系统上,它是(LEFT上的最低地址)
00000001 00000010 00000100 00001000
但是在大端系统上,字节以相反的方式存储。 LEFT仍然是最低的地址。
00001000 00000100 00000010 00000001
当你取整数a的地址并强制转换为char(字节)指针时,它指向整数中的第一个字节(最低地址)。向指针写入1时,最低字节设置为00000001.但是,char只有1个字节长,因此其他字节不变。然后第二个字节设置为00000010。
在您的示例中,512 in little endian是
00000000 00000010
Big endian更棘手,因为结果取决于int中的字节数。它通常是4,但可能是2或更多。作为2字节的int,内存中的512是
00000010 00000000
,作为一个4字节的int,它是
00000000 00000000 00000010 00000000
(对于小端,这并不重要,因为额外的字节只是零)
将1写入第一个字节,将2写入第二个字节后,将获得4字节小端的内存
00000001 00000010 00000000 00000000
一个4字节的大端
00000001 00000010 00000010 00000000
注意第三个字节中的位仍然存在。这是因为我们只写了前两个字节。第三个和第四个字节不变。
和一个2字节的大端
00000001 00000010
解释2字节或4字节内存(2字节忽略的额外零)作为正常二进制数的小端数,它是
00000000000000000000001000000001 = 513
将4字节存储器解释为大端数,作为普通二进制数,它是
00000001000000100000001000000000 = 16908800
将2字节存储器解释为大端数字作为普通二进制数,它是
0000000100000010 = 258
我可能在计算中犯了一个错误,但希望你能得到这个想法。这就是在不同类型的指针之间进行转换时需要小心的原因。
答案 3 :(得分:0)
正如其他人所指出的那样,诀窍是要了解内存和字符在内存中的表现方式。我写了一些C ++代码,试图向您展示。将其粘贴到文件中,编译和放大跑;然后更改main
中的值,看看会发生什么。这是代码:
#include <stdio.h>
// print one byte as a binary number
void print_binary(unsigned u) {
for (int i = 7; i >= 0; --i)
printf("%d", (u >> i) & 1);
}
// print a number's binary representation
template <typename T>
void print_int_binary(T i) {
char *cp = (char*)&i;
for (int i = 0; i < sizeof(T); ++i) {
print_binary(cp[i]);
printf(" ");
}
printf("\n");
}
// show how the variable is represented in memory
template <typename T>
void print_var_binary(const char *name, T t) {
printf("%s is stored as %d bytes:\n", name, (int)sizeof(t));
print_int_binary(t);
}
#define PRINT(a) print_var_binary(#a, a);
int main() {
PRINT((int)513)
PRINT((char)2)
}
当我在我的(小端)计算机上运行时,会打印出来:
(int)513 is stored as 4 bytes:
00000001 00000010 00000000 00000000
(char)2 is stored as 1 bytes:
00000010