无符号字符指向无符号整数

时间:2013-10-02 14:00:33

标签: c pointers integer char unsigned

我不明白为什么以下代码打印出来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);

10 个答案:

答案 0 :(得分:3)

你不懂二进制。这是程序员应该知道的最基本的东西之一。计算机不能使用小数。

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

假设您的系统是x86,它是小端,因此0x00030207将以0x07 0x02 0x03 0x00的形式存储在内存中,并按预期打印出来(7 2 3 0)

答案 1 :(得分:2)

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

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

中将整数表示为十进制
char E[] = "197127";

然后在字节中进行了一次异步遍历,你会看到字符的表示形式为数字。

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

e as 197127的值不是字符串表示。它存储为16/32位整数(取决于平台)。因此,在内存中,e被分配,比如堆栈上的4个字节,并且将在该内存位置表示为0x30207(十六进制)。在二进制文件中,它看起来像110000001000000111.注意“endian”实际上是向后的。请参阅此link account endianess.因此,当您将f指向& e时,您将引用数值的第一个字节,如果要将数字表示为字符串,则应该

 char *e = "197127"

答案 5 :(得分:1)

数字e的基础表示位于binary,如果我们将值转换为 hex ,我们可以看到该值为(假设为32 bit unsigned int ):

0x00030207

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

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

请注意sizeof返回size_t,正确的格式说明符为%zu,否则您有undefined behavior

您还需要修复此行:

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

为:

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

答案 6 :(得分:1)

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

你可以试试这个:

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

这将打印197127

详细了解字节顺序字节顺序here

答案 7 :(得分: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]); }

答案 8 :(得分:1)

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

答案 9 :(得分:0)

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

要获得您期望的结果,您应该更改e的声明和作业:

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

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

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

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

或者......,