关于指针类型转化后在printf输出的问题

源自CSDN论坛,自己总结了下问题及答案:http://topic.csdn.net/u/20090909/23/70292691-3cbf-45fa-9b13-c5e6d290400f.html

[code=C/C++][/code]
#include<stdio.h>

int main()
{
  unsigned int a = 0xfffffff7;
  unsigned char i = (unsigned char)a;
  char *b = (char *)&a;
  printf("%08x,%08x",i,*b);
}

输出是000000f7fffffff7
前一个是类型转化截取低8位值跟期望是一样的,可是我不明白b的指针是char *虽然它被赋予a的地址,但是现在对于b来说它的对象应该是char型变量啊,最大值应该只有8位才对,显示应该是000000f7才对,为什么是fffffff7呢?


Ans:

unsigned int和 int存储结构是4字节,a的值和它存储结构相对应是  a: 11111111 11111111 11111111 11110111

用int 型来看a的话 第一位是符号位,有符号数以补码形式存储,转化下,上面的值减1然后各位取反 就是10000000 00000000 00000000 00001001
它的符号是负,大小是9,所以它的值是-9,

比如printf("%08x,%d,%u\n",a,a,a);结果是fffffff7,-9,4294967287  ------同样存储结构,用不同的眼光看它,就会取到不同的值。


char 和 unsigned char存储结构是1字节,也就是只能取到后8位的值,即11110111 -----在这里发生了截断

unsigned char是无符号数,所以i=f7,转化成10进制是247,
char是有符号数,11110111转化为10001001,第一位是符号位,后面的值是9,*b=-9;
i,和*b虽然都由i转化而来,但取得的值不一样
printf("%08x,%08x",i,*b);就相当于printf("%08x,%08x",247,-9);
因为printf %x是打印无符号的16进制数字,正数直接输出,f7,前面不足8位,补0,就是000000f7
负数要转化成补码形式,所以*b输出时是11110111 即f7,前面补1;就成了fffffff7

上述程序中a值改为  unsigned int a = 0xAAAAAAf7;以后输出同样不变,所以之前的显示输出fffffff7与a的值fffffff7一样是巧合,事实上在指针类型转化后,值的确也被截断了,只不过符号扩展添加了24个1.


如果printf("%x,%x",i,*b);会发现*b依然是fffffff7,也就是负数是以4字节大小补码形式输出的

你可能感兴趣的:(printf)