2017-03-06 6 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'の値をとることになります...この内容をスタックまたはレジスタに残した起動コードの副作用です。 OSとスタートアップコードによっては、この値が再現可能であるかどうかは関係ありません。 UBの意味を理解しようとするのは無駄であり、アセンブリレベルの検査といくつかの魔法のスキルが必要な場合があります。 – chqrlie

2

プログラムの動作は、で、定義されていません。です。

scanfの戻り値を確認すると、渡された引数に読み込まれるデータの数がわかります。あなたのケースでは、charでの読み込みには%dを使用できないため、戻り値はゼロになります。したがってuは初期化されていないため、その値を読み取るべきではありません。

printfに余分なパラメータを渡したという事実は正式なものですが、そのような引数はまだ評価されています。 Is calling printf with excess arguments undefined behaviour?を参照してください。

ストーリーのモラル:常にscanfの戻り値を検査します。

関連する問題