文本编辑器:VS代码
编译器:minGW
我需要存储1-10之间的数字,所以我想为什么不将其存储在char变量中,因为它只需要1个字节。
所以,看看下面的代码
char a = 3;
printf("%d", a);
输出
3
运行良好
然后我决定使用scanf将值作为输入
这是的代码
char a;
printf("Enter number : ");
scanf("%d", &a);
printf("You entered : %d", a);
输出
Enter number : 9
You entered : 9
它也工作得很好,但问题在于当我尝试使用两个变量时
看看下面的代码
char a = 2, b = 3;
printf("before scanf a : %dn", a);
printf("before scanf b : %dn", b);
printf("Enter new value of a : ");
scanf("%d", &a);
printf("after scanf a : %dn", a);
printf("after scanf b : %dn", b);
输出
before scanf a : 2
before scanf b : 3
Enter new value of a : 9
after scanf a : 9
after scanf b : 0 //Notice value of b has changed to 0
尽管如此,我甚至没有触及b的价值。但它还是变了。。我想了很多办法,但都失败了,我是个初学者。我认为这与stdin/out流有关。请帮我一下。。
scanf("%d", &a);
指示scanf
读取十进制数字,并将其分配给&a
指向的int
。由于&a
指向char
,而不是int
,因此行为不由C标准定义。
正确的代码是将a
声明为signed char
并使用scanf("%hhd", &a);
。(从技术上讲,没有转换说明符可分配给char
。(
格式说明符%d
指定int,而不是char。当您将此格式说明符与printf
一起使用并传递一个char时,这并不重要,因为char会隐式提升为int。
但是使用scanf,您最终会传递一个char指针(注意scanf
使用&a
而不是简单的a
(,其中scanf
需要一个int指针。因此,scanf
最终将int复制到char中,这意味着数据溢出到相邻的内存位置。在您的情况下,该相邻位置恰好是变量b
,因此b
的值被输入的整数的MSB覆盖,在本例中为0。
附言:我还应该提到一个事实,你不应该真的依赖这种行为。我上面提到的是对你的观察最有可能的解释。这种特殊的情况属于未定义的行为,因此不同的编译器、不同的硬件或同一程序的不同运行理论上可能会导致截然不同的结果,而且这仍然是完全合法的!正确的解决方案是使用int而不是字符。在一台现代机器上,这些滑稽动作无论如何都不会让你省下多少钱。
发生的情况是,您的程序认为a属于int类型。由于int的大小是4个字节,如果您这样做:
char a = 2, b = 3, c = 4, d = 5, e = 6;
scanf("%d", &a)
将损坏b、c和d的值(但不会损坏e值,因为e是第5个字节,int大小为4(,因为scanf认为您已将指针传递给int,而不是char。