2

我不明白为什么下面的代码会打印出来,7 2 3 0我希望它会打印出来1 9 7 1。谁能解释为什么要打印7230?:

unsigned int e = 197127; 
unsigned char *f = (char *) &e;

printf("%ld\n", sizeof(e));
printf("%d ", *f); 
f++;        
printf("%d ", *f); 
f++;            
printf("%d ", *f); 
f++;            
printf("%d\n", *f);
4

10 回答 10

3

计算机使用二进制而不是十进制,因此 197127 存储为二进制数,而不是以十进制单独存储的一系列单个数字

197127 10 = 00030207 16 = 0011 0000 0010 0000 0111 2

假设您的系统使用little endian0x00030207将存储在内存中0x07 0x02 0x03 0x00,当您打印出每个字节时,它会按预期打印为 (7 2 3 0)

于 2013-10-02T14:14:48.100 回答
2

“197127”的二进制表示是“00110000001000000111”。字节看起来像“00000111”(十进制7),“00000010”(2),“0011”(3)。其余为 0。

于 2013-10-02T14:18:27.720 回答
2

因为使用您的方法,您打印出的内部表示,unsigned而不是它的十进制表示。

整数或任何其他数据在内部表示为字节。unsigned char在这种情况下,它只是“字节”的另一个术语。如果您将整数表示为字符串中的小数

char E[] = "197127";

然后对字节进行类似的遍历,您会看到字符表示为数字。

于 2013-10-02T14:13:42.280 回答
1

e 的值为 197127 不是字符串表示形式。它存储为 16/32 位整数(取决于平台)。因此,在内存中,分配了 e,例如堆栈上的 4 个字节,并且在该内存位置表示为 0x30207(十六进制)。在二进制中,它看起来像 110000001000000111。请注意,“endian”实际上会倒退。请参阅此链接帐户字节序。因此,当您将 f 指向 &e 时,您将引用数值的第一个字节,如果您想将数字表示为字符串,您应该

 char *e = "197127"
于 2013-10-02T14:15:26.757 回答
1

数字的底层表示e二进制的,如果我们将值转换为十六进制,我们可以看到该值将是(假设 32 位无符号整数):

0x00030207

因此,当您遍历内容时,您正在通过 *unsigned char ** 逐字节读取。每个字节包含两个 4 位十六进制数字,并且该数字的字节顺序字节序是小字节序,因为最低有效字节(0x07)是第一个,因此在内存中的内容如下所示:

0x07020300
  ^ ^ ^ ^- Fourth byte
  | | |-Third byte
  | |-Second byte
  |-First byte

请注意,sizeof返回size_t和正确的格式说明符是%zu,否则您有未定义的行为

您还需要修复此行:

unsigned char *f = (char *) &e;

至:

unsigned char *f = (unsigned char *) &e;
                    ^^^^^^^^
于 2013-10-02T14:16:23.493 回答
1

你知道的类型int经常发生四个字节。这意味着在内存197127中呈现。00000000 00000011 00000010 00000111从结果来看,你的内存地址是Little-Endian. 这意味着,低字节0000111分配在低地址,然后是0000001000000011最后是00000000。因此,当您首先将 f 输出为 时int,通过type cast您获得 a 7。由f++f 指向00000010,输出为2。其余的可以类推。

于 2013-10-02T14:30:00.663 回答
1

这与整数的存储方式有关,更具体地说是字节顺序。您的系统恰好有 little-endian 字节排序,即多字节整数的第一个字节是最不重要的,而最后一个字节是最重要的。

你可以试试这个:

printf("%d\n", 7 + (2 << 8) + (3 << 16) + (0 << 24));

这将打印197127.

在此处阅读有关字节顺序字节序的更多信息。

于 2013-10-02T14:18:25.517 回答
1

无符号整数的字节布局197127[0x07, 0x02, 0x03, 0x00],您的代码会打印这四个字节。

如果你想要十进制数字,那么你需要把数字分解成数字:

int digits[100];
int c = 0;
while(e > 0) { digits[c++] = e % 10; e /= 10; }
while(c > 0) { printf("%u\n", digits[--c]); }
于 2013-10-02T14:24:00.173 回答
1

你为什么期待1 9 7 1?197127 的十六进制表示是0x00030207,所以在小端架构上,第一个字节将是0x07,第二个0x02,第三个0x03和第四个0x00,这正是你得到的。

于 2013-10-02T14:14:38.397 回答
0

因为e是一个整数值(可能是 4 个字节)而不是字符串(每个字符 1 个字节)。

要获得您期望的结果,您应该更改efor 的声明和分配:

unsigned char *e = "197127";
unsigned char *f = e;

或者,将整数值转换为字符串(使用sprintf())并f指向它:

char s[1000];
sprintf(s,"%d",e);
unsigned char *f = s;

或者,使用数学运算从整数中获取单个数字并将其打印出来。

或者, ...

于 2013-10-02T14:14:07.840 回答