3

配列サイズは宣言時に指定するか、実行時にmallocを使用してヒープから割り当てる必要があることがわかったときに本を読んでいました。このプログラムはCで作成しました。

#include<stdio.h>

int main() {
  int n, i;
  scanf("%d", &n);
  int a[n];
  for (i=0; i<n; i++) {
    scanf("%d", &a[i]);
  }
  for (i=0; i<n; i++) {
    printf("%d ", a[i]);
  }
  return 0;
}

このコードは正常に機能します。

私の質問は、このコードがどのように正しく機能するかです。実行前に配列サイズを宣言するか、実行時にmalloc()を使用して配列サイズを割り当てる必要があるというのは、Cの基本概念に違反しているのではないでしょうか。では、なぜそれが正しく機能するのでしょうか?

私の質問に対する解決策は、C99でサポートされている可変長配列ですが、コードをいじってステートメントをint a[n]にすると、scanf( "%d、&n);を超えると、動作を停止します。なぜそうなのですか。Cで可変長配列がサポートされている場合はどうでしょうか。

4

4 に答える 4

5

C99標準は、可変長配列をサポートします。これらの配列の長さは実行時に決定されます。

于 2012-04-08T12:01:06.190 に答える
3

C99以降、ブロックスコープで可変長配列を宣言できます。

例:

void foo(int n)
{
    int array[n];

    // Initialize the array
    for (int i = 0; i < n; i++) {
        array[i] = 42;
    }
}
于 2012-04-08T12:01:41.967 に答える
0

Cは、使用する前に配列を宣言し、それにメモリを割り当てている限り、満足します。Cの「機能」の1つは、配列インデックスを検証しないことです。したがって、すべてのメモリアクセスが有効であることを確認するのはプログラマーの責任です。

于 2012-04-08T12:03:35.837 に答える
0

可変長配列は、C99でCに追加された新機能です。

ここでの「可変長」とは、配列のサイズがコンパイル時ではなく実行時に決定されることを意味します。配列の作成後に配列のサイズが変更される可能性があるという意味ではありません。配列は、宣言された場所に論理的に作成されます。したがって、コードは次のようになります。

int n, i;

2つの変数nとiを作成します。最初、これらの変数は初期化されていません。

scanf("%d", &n);

値をnに読み込みます。

int a[n];

サイズがnの現在の値である配列「a」を作成します。

2番目と3番目のステップを入れ替えると、初期化されていない値によってサイズが決定される配列を作成しようとします。これはうまく終わらない可能性があります。

C標準では、配列の格納方法を正確に指定していませんが、実際には、ほとんどのコンパイラー(いくつかの例外があると思います)が配列をスタックに割り当てます。これを行う通常の方法は、関数のプリアンブルの一部としてスタックポインタを「フレームポインタ」にコピーすることです。これにより、関数は自身のスタックフレームを追跡しながら、スタックポインタを動的に変更できます。

可変長配列は注意して使用する必要がある機能です。コンパイラは通常、スタック割り当てにオーバーフローチェックの形式を挿入しません。オペレーティングシステムは通常、スタックの後に「ガードページ」を挿入してスタックオーバーフローを検出し、エラーを発生させるかスタックを拡大しますが、十分に大きなアレイはガードページを簡単にスキップできます。

于 2019-02-11T16:05:00.667 に答える