2017-03-06 72 views
2

我跑這個代碼當我們使用%d掃描一個字符時會發生什麼?

#include <stdio.h> 
int main() 
{ 
    int u; 
    scanf("%d",&u); 
    printf("%d\n",u,u); 
    return 0; 
} 

下面是輸入和輸出:

input:a output:32765 
input:b output:32765 
input:c output:32767 
input:/ output:32766 

任何人都可以解釋這種現象?

+3

'scanf'失敗,返回0並且代碼中的下一條語句執行。這與'scanf'行不在那裏一樣。簡而言之,當你試圖打印一個未初始化的變量時,你的代碼調用未定義的行爲 –

回答

2

scanf()讀取輸入時,它不能根據規範進行轉換,它會停止掃描並返回成功轉換的次數。在你的情況下,字符保留在標準輸入緩衝區中,scanf()返回0

您的代碼具有未定義的行爲,因爲scanf()未能將輸入轉換爲整數,因此未對u進行初始化。將未初始化的值傳遞給printf具有未定義的行爲。在你的情況下,會打印一個稍微隨機的值,這個值可能不同或不一樣,但是包括崩潰在內的任何其他行爲都是可能的。

您必須測試返回值scanf()以檢查轉換是否成功。這裏是一個修改版本:

#include <stdio.h> 

int main(void) { 
    int u, res; 
    res = scanf("%d", &u); 
    if (res == 1) { 
     /* conversion succeeded */ 
     printf("%d\n", u); 
    } else 
    if (res == 0) { 
     /* conversion failed */ 
     printf("input is not a valid number\n"); 
    } else { 
     /* res must be EOF */ 
     printf("premature end of file: no input given\n"); 
    } 
    return 0; 
} 
+0

我知道它是UB,但是,代碼的輸出隱藏在'32767'周圍的原因是什麼? –

+0

@CoolGuy:未初始化的變量'u' *發生*有時具有值'32767' ...對於離開堆棧或註冊該內容的啓動代碼有副作用。根據操作系統和啓動代碼,該值可能是可重現的或不可重現的。試圖理解UB是相當徒勞的,可能需要組裝級別檢查和一些魔法技能。 – chqrlie

2

程序的行爲是undefined

您應該檢查返回值scanf,它會告訴您讀入傳入參數的數據的數量。在你的情況下,返回值將爲零,因爲%d不能用於讀取char。因此u未初始化,因此不應讀取其值。

請注意,您已將多餘參數傳遞給printf的事實是良性的,儘管在形式上仍會評估此類參數。請參閱Is calling printf with excess arguments undefined behaviour?

故事的寓意:總是檢查返回值scanf

相關問題