user-0 提问: 关于scanf()的一些小疑问

回复:
user: user-1
content: 7楼解释出了本质，其实char和int可以互相转换，在编译时只是警告，并不会出错，而char在内存中占1个字节，int占2个或者4个（与编译器有关），按4位看，第二个输入的int型覆盖了第一个的底24位，只留下高8位8个0，而后面的24为全部存储了。

user: user-2
content: 引用 9 楼 JackXJack 的回复:我对这道题目的理解是：a,b,c,d定义为字符型变量，但字符型变量也对应着ASCLL码。a读取6，b读取5，c读取65，d读取66，打印输出65和66对应的字符A和B。但是6和5这个关系我搞不清楚，开头定义的int，到scanf()里面又出现了%c，应该是ASCLL码6和5对应的字符。。。我凌乱了 你scanf用%c读的a,b;printf时也用的%c，所以打出来就是字符'6','5';如果printf("%d,%d",a,b);打出来就是‘6’，‘5’的ASCLL值54，53

user: user-3
content: 理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

user: user-4
content: 引用 8 楼 JackXJack 的回复:[quote=引用 7 楼 dooX8086 的回复:]  // --------------------------- //这跟你发的帖子不一样。这里是正常输入  //------------------------------------------------------- scanf 不是会检查被写入的地址, 它只会根据格式控制符，往里写数据。 scanf %c --->&a : 根据格式控制符 %c 读取到的是一个  '6' 字符，ascii 码是 54, 而不是数值 6 写入数据: a  | 54 | -- | -- | -- |  ,还有3个 byte 空闲  变量b 也是一样...  如果把 printf 改成 printf("%d, %d, %c, %c\n", a, b, c, d); //结果是想像中的  ??? 54, 53, A, B  如果是 debug 版会是这个结果，但如果 release版... .那就是不一定能输出 变量 a:54   b:53 的值了 因为 int a, b ...   没有初始化...

user: user-0
content: 我对这道题目的理解是：a,b,c,d定义为字符型变量，但字符型变量也对应着ASCLL码。a读取6，b读取5，c读取65，d读取66，打印输出65和66对应的字符A和B。但是6和5这个关系我搞不清楚，开头定义的int，到scanf()里面又出现了%c，应该是ASCLL码6和5对应的字符。。。我凌乱了

user: user-0
content: 引用 7 楼 dooX8086 的回复:溢出写入... scanf 不是会检查被入的址的. scanf %d ---->&a  :  从地址 &a 这里开始根据格式控制符%d的要求, 写入 4 个字节..  如:char a, b 在栈中的排列一般为, (不同编译器会有所不同) |0x 低位-------------------------------------->| 高位 |----------&b[1 byte]|&a[ 1 byte]-----------|  如果是 scan %d ----> &b , 即从&b开始写入4个byte---->将覆盖 a 各其后面的 3 个 byte  如写一段这样的测试  #include <stdio.h>  int main(int argc, char *argv[]) {  	char at[4] = {0}, a=0, b=0;  	scanf("%x", &b); 	 	printf(" a:%x,  b:%x\n", a, b); 	printf("at:%x\n", *((int *)at));  	return 0; }  // 输入  abcd1234  // 在小端环境中 // 结果有可能是   a:12,  b:34 at:abcd  // 也有可能是 a:0, b:34 at:0 /// 然后报错... 等行为. ///  // 在大端环境中 // 可能是 a:cd, b:ab at: 1234 // 有点头晕.... // .... //....   // 溢出其结果是(行为)不确定的，有依赖其环境(只要是编译器) // 所以不要纠结其结果， // 所以溢出的 bug 也是狠难查的...d写的太深刻了，不明觉厉啊！！！非常感谢您的回答！我之所以附上两张图是由一道题目启发的，大神若有空可帮我看看这道题目，后面输出A和B我理解，但是我不知输出6和5的原因。。。希望您能赐教！

user: user-4
content: 溢出写入... scanf 不是会检查被入的址的. scanf %d ---->&a  :  从地址 &a 这里开始根据格式控制符%d的要求, 写入 4 个字节..  如:char a, b 在栈中的排列一般为, (不同编译器会有所不同) |0x 低位-------------------------------------->| 高位 |----------&b[1 byte]|&a[ 1 byte]-----------|  如果是 scan %d ----> &b , 即从&b开始写入4个byte---->将覆盖 a 各其后面的 3 个 byte  如写一段这样的测试  #include <stdio.h>  int main(int argc, char *argv[]) {  	char at[4] = {0}, a=0, b=0;  	scanf("%x", &b); 	 	printf(" a:%x,  b:%x\n", a, b); 	printf("at:%x\n", *((int *)at));  	return 0; }  // 输入  abcd1234  // 在小端环境中 // 结果有可能是   a:12,  b:34 at:abcd  // 也有可能是 a:0, b:34 at:0 /// 然后报错... 等行为. ///  // 在大端环境中 // 可能是 a:cd, b:ab at: 1234 // 有点头晕.... // .... //....   // 溢出其结果是(行为)不确定的，有依赖其环境(只要是编译器) // 所以不要纠结其结果， // 所以溢出的 bug 也是狠难查的...

user: user-5
content: 你单步跟一下看看内容

user: user-5
content: 好像说的看错了，忽略我上面说的。

user: user-0
content: 引用 3 楼 haitunxiaomo 的回复:第二种你把地址符去掉试试看。输入字符的时候一般使用地址符的。试了，程序停止工作

user: user-5
content: 第二种你把地址符去掉试试看。输入字符的时候一般使用地址符的。

user: user-0
content: 我的问题：scanf()函数要按照变量的数据类型指定与该数据类型相匹配的格式字符，但上图中scanf()内的数据类型和最开始指定的数据类型不匹配，不应该是相当于遇到非法字符吗？请各位具体地解释一下上面两种情况，尤其是第二种情况，拜谢各位！

user: user-0