最近、プログラマーがif/else条件に応じて 1 つの無限ループ内で変数を宣言しているソース コードを見つけました。私が奇妙だと思ったのは、コードが実行され、メモリ リークが発生していないことです。最初は、おそらくアーキテクチャ固有のもの (コードは ARM 用) だと思っていましたが、いくつかのテストを実行したところ、GCC でコンパイルされた IA32 のバイナリが同じように動作することがわかりました。
私のアプローチは次のようなものでした: 2 つの小さなプログラム foo.c と bar.c を作成しました。
Foo.c:
#include <stdio.h>
int main(void)
{
int i;
for(i=0; i<10; i++) {
char buf[10];
buf[i] = 0;
printf("buf[%d] (@ %#x) == %d\n", i, &buf, buf[i]);
}
return(0);
}
Bar.c:
#include <stdio.h>
int main(void)
{
int i;
for(i=0; i<10; i++) {
char *ptr;
ptr = (char *) malloc(10);
ptr[i] = 0;
printf("buf[%d] (@ %#x) == %d\n", i, &ptr, ptr[i]);
}
return(0);
}
Foo.c で配列を宣言することと Bar.cでメモリを割り当てることを明示的に区別する理由は、コンパイラが自動的にそれが同じ変数であることを自動的に検出し、イニシャルの後の宣言を単に無視して反復するのではないかと最初に考えたからです。メモリを明示的に割り当てるため、 Bar.cではそうではありません。
両方の例で、配列と割り当てられたメモリの両方のアドレスが、反復の初期化後に同じままであることは、私にとって本当に奇妙でした。
私はそれを完全には理解していませんし、私はK&Rのコピーを持っていないので、説明に感謝します. (また、私の推論に間違いがあれば、それを指摘していただければ幸いです。)