6

学校のプロジェクトで、C を使用した情報システムがありました。生徒の記録の動的なサイズのリストを保持するために、リンクされたリスト データ構造を使用しました。今朝、友人が彼のシステムを見せてくれました。私は彼の記録のリストに驚いた:

#include <stdio.h>
/* and the rest of the includes */

/* global unsized array */
int array[];

int main()
{
    int n;
    for (n=0; n < 5; n ++) {
         array[n] = n;
    }


    for (n=0; n < 5; n ++) {
         printf("array[%d] = %d\n", n, array[n]);
    }
    return 0;
}

コードと同様に、彼はプログラム全体に対して (bss セグメントで) グローバルなサイズのない配列を宣言しました。彼は、次のように配列をトラバースできるように、メモリの後続のブロックをゼロ以外の値で上書きすることにより、配列に新しいエントリを追加することができました。

for (n=0; array[n]; n++) {
    /* do something */
}

彼はTurbo C v1を使用しました(私もテストしました)。Linuxで試してみましたが、動作します。

以前にこの手法に遭遇したことがないので、問題があると推測しています。それで、ええ、なぜこれが悪い考えなのか、そしてリンクされたリストよりもこれを好む理由を知りたい.

4

3 に答える 3

7
int array[];

技術的には、不完全型の配列として知られています。簡単に言えば、次と同等です。

int array[1];

これは単に次の理由で良くありません。

  1. 未定義の動作が発生します。不完全型の配列の主な用途はStruct Hackです。C99 で標準化された不完全な配列型は、以前は違法であったことに注意してください。
于 2013-03-09T14:56:16.177 に答える
4

これは未定義の動作です。割り当てられていないメモリ (配列の外) に書き込んでいます。これをコンパイルするために、コンパイラは少なくとも 1 つの要素を割り当てており、それを超えて記述しています。より大きな数値範囲を試してください。たとえば、Linux でコードを実行すると動作しますが、ループを 50,000 に変更するとクラッシュします。

編集コードは小さな値では機能するかもしれませnんが、大きな値では失敗します。これを実証するために、私はあなたのコードを書き、n = 1000.

これはCODEPADのリンクです。n = 1000 の場合、セグメンテーション違反が発生することがわかります。

同じコンパイラで同じコードを使用すると、n = 10 で動作します。このリンクCODEPADを参照してください。したがって、これは未定義の動作と呼ばれます。

于 2013-03-09T15:00:43.790 に答える
0

リンクされたリストを使用すると、メモリが適切に割り当てられているかどうかを確認できます。

int *ptr;
ptr = (int *)malloc(sizeof(int))
if(ptr==NULL)
{
  printf("No Memory!!!");
}

しかし、あなたのコードでは、大きな境界を持つ配列でテストすると、プログラムは単純にクラッシュします。

于 2013-03-09T15:13:24.733 に答える