#include <stdio.h>
int main(void) {
int a = 0;
printf("a = %d, foo = %d\n", a); return 1;
}
上記のようなプログラムを実行したところ、
コンパイルエラーとはならず
下記のような結果が出力されました。
$ a = 0, foo = -1074283144
書式文字列で指定した変数の数と
実際に引数で指定した変数の数が違う場合、
不一致している部分にはどんな値が
*言語仕様上*入るのでしょうか?
参考になるウェブサイトでも良いので
教えてください。
個定数引数の場合はプロトタイプ記述でコンパイラに検知させる手段がありますが、可変引数の場合は引数の数をコンパイラにチェックさせる手段はありません。
歴史的にはプロトタイプ記述は割と最近できた言語仕様で、初期のC言語にはプロトタイプ記述も無く、個定数引数の場合でも引数の数の整合性をチェックするのはコンパイラの仕事では無く、プログラマの注意力に委ねられていたのです。C言語とは本来そのような言語です。
従って、この問題も言語仕様として規約があるわけではありませんし、コンパイルエラーにならないのも同じ理由です。
C言語の引数はスタック渡しですので、引数の数が足りなくても多過ぎても、単に関数側がスタックに引数が積まれているものと*信用している*に過ぎません。
例えば、n個の引数を期待している関数に(n-1)個の引数しか渡さなかった場合、呼ばれた関数はとにかく1~n番目のスタックを引数とみなします。
n番目のスタックは値がセットされていませんので、不定値、つまりその時たまたまn番目のスタックに入っている値をprintfが利用するだけの話です。
【3個の引数が正しく渡される場合】
printf("a = %d, b = %d, c = %d\n", 1,2,3);
スタックの状態
┌─┐
│1│
├─┤
│2│
├─┤
│3│
└─┘
【引数が足りない場合】
printf("a = %d, b = %d, c = %d\n", 1,2);
スタックの状態
┌─┐
│1│
├─┤
│2│
├─┤
│?│←何が入っているか保証されないが、printfはとにかくこの中の値を書式印刷する
└─┘
フォーマット文字列の解釈やデータ引数との対応については、コンパイラはいっさいチェックしません
http://www.h4.dion.ne.jp/~zero1341/win90/901.htm
----------------------------------------------------
値は不確定になるのが仕様のはずですが・・。
言語仕様? printfの関数仕様では決まってないはずで
実装はコンパイラや処理系によって違うはず。
「未定義」
コンパイルエラーとはならず
一般的には、書式文字列と可変個の引数が一致しているかは検査されません。
gcc 等の一部のコンパイラなどは警告してくれる場合はあります。
書式文字列で指定した変数の数と実際に引数で指定した変数の数が違う場合
引数が足らない場合の動作は未定義です。
何か出力されるかもしれないし、プログラムが異常終了するかもしれません。
個定数引数の場合はプロトタイプ記述でコンパイラに検知させる手段がありますが、可変引数の場合は引数の数をコンパイラにチェックさせる手段はありません。
歴史的にはプロトタイプ記述は割と最近できた言語仕様で、初期のC言語にはプロトタイプ記述も無く、個定数引数の場合でも引数の数の整合性をチェックするのはコンパイラの仕事では無く、プログラマの注意力に委ねられていたのです。C言語とは本来そのような言語です。
従って、この問題も言語仕様として規約があるわけではありませんし、コンパイルエラーにならないのも同じ理由です。
C言語の引数はスタック渡しですので、引数の数が足りなくても多過ぎても、単に関数側がスタックに引数が積まれているものと*信用している*に過ぎません。
例えば、n個の引数を期待している関数に(n-1)個の引数しか渡さなかった場合、呼ばれた関数はとにかく1~n番目のスタックを引数とみなします。
n番目のスタックは値がセットされていませんので、不定値、つまりその時たまたまn番目のスタックに入っている値をprintfが利用するだけの話です。
【3個の引数が正しく渡される場合】
printf("a = %d, b = %d, c = %d\n", 1,2,3);
スタックの状態
┌─┐
│1│
├─┤
│2│
├─┤
│3│
└─┘
【引数が足りない場合】
printf("a = %d, b = %d, c = %d\n", 1,2);
スタックの状態
┌─┐
│1│
├─┤
│2│
├─┤
│?│←何が入っているか保証されないが、printfはとにかくこの中の値を書式印刷する
└─┘
コメント(2件)
違うと思います。そもそも検査不可能です。
(書式文字列が即値の文字列リテラルの場合は可能ですが。)
> C言語の引数はスタック渡しです
決まっていないと思います。
(そもそもスタックがあるとは限らないらしいし。)