![](/img/trans.png)
[英]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.