私が C を教えているとき、いくつかのルールの「説得力のある」部分を GCC に任せることがあります。たとえば、関数のローカル変数が呼び出し間で値を保持しているとは考えないでください。
GCC は常に学生にこれらの教訓を教え、ローカル変数にゴミを入れて、学生が何が起こっているのかを理解するのを助けてくれました。
さて、このコードは間違いなく私を苦しめています。
#include <stdio.h>
int test(int x)
{
int y;
if(!x)
y=0;
y++;
printf("(y=%d, ", y);
return y;
}
int main(void)
{
int a, i;
for(i=0; i<5; i++)
{
a=test(i);
printf("a=%d), ", a);
}
printf("\n");
return 0;
}
出力は次のとおりです。
(y=1, a=1), (y=2, a=2), (y=3, a=3), (y=4, a=4), (y=5, a=5),
しかし、次の行にコメントすると:
/* printf("(y=%d, ", y); */
出力は次のようになります。
a=1), a=32720), a=32721), a=32722), a=32723),
スイッチを使用してコードをコンパイルしました-Wall
が、初期化せずにローカル変数を使用しても警告は表示されません。
警告を発生させる、または少なくともガベージを明示的に表示する GCC スイッチはありますか? 最適化スイッチを試してみたところ、コード出力が次のようになったので役に立ちました。
$ gcc test.c -o test -Wall -Os
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -Ofast
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -O0
$ ./test
(y=1, a=1), (y=2, a=2), (y=3, a=3), (y=4, a=4), (y=5, a=5),
$ gcc test.c -o test -Wall -O1
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -O2
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
$ gcc test.c -o test -Wall -O3
$ ./test
(y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1), (y=1, a=1),
しかし、すべての場合で y=1 は一種のトリックです。ローカル変数がゼロで初期化されるように標準が変更されましたか?