[英]Why in C does taking input using int format to a char change the value of another char variable?
我使用 scanf() 将“%d”格式的输入输入到一个字符中,因为我不想要超过 8 位。 但是这样做会改变另一个 char 变量的值。
代码:
#include <stdio.h>
int main() {
char a;
char b;
printf("Enter a: ");
scanf("%c", &a);
printf("a = %c\n", a);
printf("Enter b: ");
scanf("%d", &b);
printf("\na = %d\n", a);
printf("b = %d\n", b);
}
Output:
Enter a: c
a = c
Enter b: 56
a = 0
b = 56
scanf 从标准输入读取数据并根据参数格式将它们存储到附加的 arguments 指向的位置。
scanf("%d", &b);
使用 %d,您将 integer 存储到无法保存 integer 的 char 变量中。 变量现在增长到它上面的堆栈中的另一个变量。
如果您使用标志“-fstack-protector-all”进行编译,您应该会在执行时得到 *** 检测到堆栈粉碎 *** 错误。
重复使用scanf()
function 时会出现此问题。 由于scanf()
不会自动跳过 stream 中的空格,因此必须在 %c 转换说明符前面留一个空格。
我在ISO C11 (-std=c11)
模式下使用 GCC 编译器来调查这个问题。
#include <stdio.h>
#include <stdlib.h>
/**
* @brief Main Program
* @return Returns 0 if the program is successful.
*/
int main( void )
{
char a;
char b;
printf( "Enter the value of a: " );
scanf( "%c", &a );
printf( "Enter the value of b: " );
scanf( " %c", &b );
/// A space has been added in front of the %c conversion identifier of the scanf() function.
printf( "The value of variable a: %d\n", a );
printf( "The value of variable b: %d\n", b );
return EXIT_SUCCESS;
}
Screenshot 1:
测试应用程序
@JBahn77 谢谢。 我刚刚注意到第二个scanf()
function 使用%d
转换令牌。 我同意你指出的副作用。 当编译器一个接一个地加载 memory 中的变量时,就会发生这种情况。 例如,当在变量 b 中输入足够大的数字时,我检查了变量 a 的变化。 我将代码更改如下。
#include <stdio.h>
#include <stdlib.h>
/**
* @brief Main Program
* @return Returns 0 if the program is successful.
*/
int main( void )
{
char a;
char b;
printf( "Address of variable a: %p\n", &a );
printf( "Address of variable b: %p\n", &b );
printf( "Enter the value of a: " );
scanf( "%c", &a );
printf( "Enter the value of b: " );
scanf( " %d", &b );
printf( "The value of variable a: %d\n", a );
printf( "The value of variable b: %d\n", b );
return EXIT_SUCCESS;
}
然后,当我测试代码时,我意识到了这种副作用的后果。
Screenshot 1
:测试编辑后的代码
测试代码如下图所示。
Screenshot 2
:结果解读
scanf
格式字符串中的格式化指令不仅指示如何匹配输入,还指示要存储结果值的相应变量的类型。 如果你传递一个指向 object 的指针,它的类型与相应指令所期望的不同,那么你将获得未定义的行为。
即使对于简单的符号不匹配也是如此,但在您的情况下,您的大小不匹配。 对于没有大小修饰符的%d
指令, scanf
期望将扫描的 integer 值写入 [ signed
] int
类型的 object 中。 如果您传递的指针改为指向char
,并且在大多数实现中,如果int
大于char
,那么产生的未定义行为特别有可能以不需要的方式表现出来,例如通过在其他变量的值。
如果要将数字扫描为char
大小的 integer,那么您应该
signed char
或unsigned char
,而不是默认char
,并且例如,
unsigned char b;
scanf("%hhu", &b);
%u
是无符号 integer 的格式指令,并且hh
修饰符指示scanf
目标变量是char
/ signed char
/ unsigned char
的大小。
如果你想要一个签名的 integer 那么它会是相似的,但是使用%d
格式化指令:
signed char b;
scanf("%hhd", &b);
作为一种风格,不要将默认char
用于数字数据,即使您确信需要支持的值范围是有signed char
和unsigned char
范围交集的子集。 特别是如果您打算将它与格式化的 I/O 函数一起使用,因为%hhd
或%hhu
是否是默认char
的正确指令是特定于实现的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.