16

テーブルを印刷するプログラムを作成しました。main関数にreturn構文を含めていませんが、echo $と入力するたびに?12が表示されます。

私のソースコード:

#include <stdio.h>


int main(void)
{
    int ans,i,n;
    printf("enter the no. : ");
    scanf("%d",&n);

    for(i=1;i<=10;i++)
    {
        ans = n*i;
        printf("%d * %d = %d\n",n,i,ans);
    }
}

私はreturn12を書いていませんが、それでもプログラムを実行するたびに12を返します。

ありがとう。

4

4 に答える 4

20

swegi が言うように、それは未定義の動作です。 Steve Jessop らが言うように、C89 までは未規定値であり、C99 で規定されています (観察された動作は C99 に準拠していません)。

ほとんどの環境で実際に起こることは、最後の戻り値がprintf戻り値に使用されるレジスターに残されることです。

したがって、n == 0 の場合は 11、n が 1 桁の場合は 12、2 桁の場合は 14、3 桁の場合は 16 などになります。

于 2010-09-16T13:26:35.923 に答える
19

既存のすべての回答が未定義の動作であると言っているため回答しますが、これは真実ではないため、賛成できるものは何もありません。

C89 (ドラフト標準への参照について pmg に感謝)、5.1.2.2.3:

main 関数への最初の呼び出しから戻ることは、main 関数によって返された値を引数として exit 関数を呼び出すことと同じです。メイン関数を終了する } に達した場合、ホスト環境に返される終了ステータスは不定です。

C99 では、n1256、5.1.2.2.3 から引用:

メイン関数の戻り値の型が int と互換性のある型である場合、メイン関数への最初の呼び出しからの戻りは、メイン関数によって返された値を引数として exit 関数を呼び出すことと同じです。メイン関数を終了する } に到達すると、値 0 が返されます。戻り値の型が int と互換性がない場合、ホスト環境に返される終了ステータスは規定されていません。

つまり、「未定義の動作」でmainはありません。関数が返されるかのように動作しますが、C89 では、返される値は標準で指定されていません。サンプル プログラムの場合、実装では、返される値は一貫して 12 のように見えます。これは、おそらく Ben Voigt が言っている理由によると思われます。あなたは Linux を使っているので、コードを C99 としてコンパイルすること (またはとにかく、gcc のほぼ準拠の C99 モードを使用してコンパイルすること) はおそらく大きな変更ではありません。

以外の値を返す関数のmain場合、呼び出し元が戻り値を使用しない限り、未定義の動作です(n1256、6.9.1/12):

関数を終了する } に到達し、関数呼び出しの値が呼び出し元によって使用された場合、動作は未定義です。

mainへの最初の呼び出しが、この一般規則から除外されていると言及されるべきかどうかはわかりません。である必要はありません: 標準の POV からすると、その呼び出しには呼び出し元が存在しないため、関数呼び出しの値は、終了状態になるにもかかわらず、「呼び出し元によって使用される」ことはないと思います。プログラムのために。

于 2010-09-16T15:22:26.703 に答える
1

アセンブリ言語に精通している場合は、関数の「戻り値」が EAX レジスタを介して渡されることを思い出すかもしれません。

この場合、戻り値は EAX から読み取られています。この場合、たまたま 12 です。

ただし、この値を明示的に設定しているわけではありません。これは、コードの残りの部分からの単純なアーティファクトです (または、偶然の可能性があります)。

言われている通り、これは間違いないundefined behavior。なぜこのような結果になるのか単純に知りたい場合は、この説明を検討してください。

ただし、いかなる状況でも、この値を意味のあるものとして意図的に使用しようとしないでください。

于 2010-09-16T13:25:25.340 に答える
0

あなたのプログラムは、本来あるべきときに何も返さないことで未定義の動作を引き起こしています。したがって、呼び出し元は通常、プロシージャの戻り時に eax レジスタ (x86 では、x64 では rax) の値が何であれ取得します。 eax の最後の使用 (値を返す関数または単にレジスタ ベースの変数による)。この場合、おそらく printf が stdout バッファに書き込んだ char の量です。

于 2010-09-16T13:30:40.293 に答える