有以下一段程序:
int i;
char c;
for (i=0;i <5;i++)
{
scanf("%d",&c);
printf("i=%d/r/n",i);
}
乍看很简单,可真正运行以后,发现问题并不是这么简单
1.当你输入数字时,每次输入都会提示你输入
2.当你输入字符时,不会提示你输入
3.可能输出000001234
因为c的声名是char而不是int。当你令scanf()去读取一个整数时,它需要一个指向一个整数的指针。但这里它得到的是一个字符的指针。但scanf()并不知道它没有得到它所需要的:它将输入看作是一个指向整数的指针并将一个整数存贮到那里。由于整数占用比字符更多的内存,这样做会影响到c附近的内存。c附近确切是什么是编译器的事;在这种情况下这有可能是i的低位。因此,每当向c中读入一个值,i就被置零。当程序最后到达文件结尾时,scanf()不再尝试向c中放入新值,i才可以正常地增长,直到循环结束,同时函数scanf要求读一个数,如果你输入一个字符,那么scanf会执行失败,那个字符还会在缓冲区内,致使缓冲区一直保持有效,所以当你输入字符时,不会提示你输入。
unsigned int a = 0xaaaaaaa7;
unsigned char i = (unsigned char)a;
char *b = (char *)&a;
printf("%08x,%08x",i,*b);
按照上面所说,printf应该%x要求用一个int指针去读数据,而现在是char型,会不会读b的时候造成多读了3个字节呢?没错,理论上应该是这样,可事实上是,b数据在函数中已被提升为一个int型数据,然后再按%x打印出来。
ps:在C语言中,调用一个不带原型声明的函数时:调用者会对每个参数执行“默认实际参数提升(default argument promotions)”。
ps:无论什么时候printf打印的是变量的值,不要看到格式串中有个%p,就以为是打印变量的地址。当遇到%s的时候,会把变量的值解析成一个地址,输出这个地址指向的值。
【练习】
int i;
short *ps = (short *)(&i);
char *pc = (char *)(&i);
i = 0;
*ps = 1;
printf("%x/t%x/t%x/n", i, *ps, *pc);//1 1 1
i = 0;
*ps = 256;
printf("%x/t%x/t%x/n", i, *ps, *pc);//100 100 0
i = 0;
*ps = -1;
printf("%x/t%x/t%x/n", i, *ps, *pc);//ffff ffffffff ffffffff
printf("%d/t%d/n", '0', '/0');//48 0