[英]Can `unsigned int x; scanf("%u",&x);` really cause undefined behavior?
[英]entering a char using scanf and saving it in an int can cause undefined behaviour?
我正在编写代码,尝试输入一个char而不是整数,无论输入的字符如何,结果均为'2',这是未定义的行为还是其他原因?
编码:
#include <stdio.h>
int f1(int n);
int f2(void);
int main(void)
{
int t;
printf("Enter a number: ");
scanf("%d", &t);
/* print proper message */
t ? f1(t) + f2() : printf("zero entered.\n");
return 0;
}
int f1(int n)
{
printf("%d ", n);
return 0;
}
int f2(void)
{
printf("entered.\n");
return 0;
}
当我输入a
,结果为“ 2输入”,当我输入g
,结果为“ 2输入”,而当我输入i,h,k,.....
,结果是相同的。 那是什么?
如果scanf()
遇到无法根据指定的格式字符串进行解析的内容,它只会停止并提早返回。 因此,它永远不会向t
写入任何内容(您只是看到在调用之前t
具有任何不确定的值)。
要处理此问题,您应该始终检查scanf
的返回值。
正如您所说,问题是使用%d格式的scanf要求您输入一个或多个ascii数字。 它停止以非数字字符扫描输入,因此它从不读取您键入的内容,并且t具有调用scant之前的值。
您需要检查scanf
的返回码。 看一下联机帮助页 :
返回值
这些函数返回成功匹配和分配的输入项的数量,该数量可能少于所提供的数量,在早期匹配失败的情况下甚至为零。
如果在第一次成功转换或匹配失败发生之前到达输入结束,则返回EOF值。 如果发生读取错误,也会返回EOF,在这种情况下,将设置流的错误指示符(请参见ferror(3)),并且设置errno表示错误。
换句话说, scanf
不会将任何内容写入t
,而是一直未初始化。
因此,代替此:
scanf("%d", &t);
尝试这个:
int items_matched = scanf("%d", &t);
if (items_matched != 1) {
printf("bad number entered\n");
exit(1);
}
这是因为scanf
无法解析您的输入。 由于您使用%d
因此希望您输入一个十进制数字 。
您必须检查scanf
的返回值以避免这种行为:
成功时,该函数返回已成功填充的参数列表的项目数。 由于匹配失败,读取错误或文件结尾的范围,此计数可以与预期的项目数匹配或更少(甚至为零)。
因此:
int items_matched;
// ...
items_matched = scanf("%d", &t); // Get the return value
if ( items_matched != 1 ) // Check it
{
printf("Matching failure with scanf.\n");
return 0;
}
else
{
if ( t == 0 )
printf("zero entered\n");
else
printf("%d entered\n", t);
}
您不需要令人困惑的f1(t) + f2()
。
格式字符串由一系列指令组成,这些指令描述了如何处理输入字符的序列。 如果指令处理失败,则不会再读取任何输入 ,并且scanf()返回。 “失败”可以是以下之一:输入失败(表示输入字符不可用)或匹配失败(表示输入不合适)。
在scanf( 7.21.6.4 scanf函数 )的C11标准描述中:
如果在第一次转换(如果有的话)完成之前发生输入失败,scanf函数将返回宏EOF的值。 否则,scanf函数将返回分配的输入项目数, 如果早期匹配失败 ,该数目可能少于所提供的输入项数, 甚至为零 。
重点是我的。 因此,正如@oli charlesworth所说,如果有疑问,应检查scanf的返回值:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.