正确认识printf和scanf函数

来源:互联网 发布:店铺数据在哪里 编辑:程序博客网 时间:2024/05/17 22:56

有以下一段程序:

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

 

原创粉丝点击