4

ここでのC99の違いに少し混乱しています。

int myfunc (int array[n], int n) { ... }

コンパイルされません。私の知る限り、常に配列サイズへの参照を最初に配置する必要があるため、次のように記述する必要があります。

int myfunc (int n, int array[n]) { ... }

ただし、staticキーワードを指定すると、これは完全に正常に機能します。

int myfunc (int array[static 1], int n) { ... }

配列を関数呼び出しで最初に配置することに慣れているので、この順序は私にとってはるかに好ましいですが、なぜこれが可能ですか?

編集:3番目の例が実際にはVLAではないことに気付くと...

参考までに、これは私が見ていたコードの一部であり、次の質問につながりました。

int sum_array(int n, int m, int a[n][m])
{
  int i, j, sum = 0;
  for (i = 0; i < n; i++)
    for (j = 0; j < m; j++)
      sum += a[i][j];
  return sum;
}
4

5 に答える 5

8

理由

int myfunc (int n, int array[n]) { ... }

有効であり、

int myfunc (int array[n], int n) { ... }

これは、Cの字句スコープ規則によるものではありません。スコープに導入される前に識別子を使用することはできません。この規則にはいくつかの例外がありますが、これはそれらの1つではありません。

編集:ここにC標準の関連する段落があります:

(C99、6.2.1p7)「他の識別子には、宣言子の完了直後に開始するスコープがあります。」

このルールは、関数プロトタイプスコープでのパラメーター宣言にも適用されます。

于 2012-08-30T22:03:36.540 に答える
2

エラーの理由はすでに説明されています。他の宣言で使用するn 前に、宣言する必要があります。

ただし、ご存知のように、これらの宣言のいずれも実際には可変長配列を宣言していないことに注意してください。

with構文がC99で最初に許可され、正式にはVLA宣言であることは事実です[n]が、それでも、C89 / 90で常に行われていたように、これらの宣言はすべて、型arrayのパラメーターとして宣言されます。int *その[n]部分はいかなる種類のヒントでもありません。この宣言で使用できるという事実[n]は、確かにVLAサポートの副作用ですが、これでVLAとの関係が終了します。それ[n]は単に無視されます。

「ヒント」宣言にはstatic、内にキーワードが必要[]です。したがって、withの宣言は、少なくとも要素が。で指定されたメモリ位置に存在する必要があるというヒントをコンパイラに与えることを除いて、従来の宣言(無視され、パラメータの型が)[static 1]と同等です。int array[1]1int *1array

于 2012-08-30T22:07:49.870 に答える
1

これは、配列を定数値で宣言する必要があるため、可変サイズを使用して配列を作成できず、したがって可変サイズの配列を渡すことができないためです。また、それが単一次元の配列である場合は、値を渡す必要はまったくありません。これは、配列の長さを示す2番目のパラメーターを渡すポイントです。

これを正しく機能させるには、次のように関数ヘッダーを記述します。

int myfunc (int myArray[], int n) {...}

順序は重要ではありませんが、渡す配列のサイズを可変にすることはできません。定数値である必要があります。

于 2012-08-30T21:58:44.500 に答える
1

GCCを使用していて、それらの拡張機能のいくつかを使用する意思がある場合は、ここで目的を達成できます。

int myFunc (int len; /* notice the semicolon!! */ int data[len], int len)
{

}

この拡張機能(可変長配列)のドキュメントはこちらです。

この拡張機能は、何らかの理由でclangで使用できないことに注意してください。ただし、理由はよくわかりません。

于 2012-08-30T22:07:40.260 に答える
-1

編集:もちろん、ダープ、スコープ。

私の質問は; なぜあなたはそれをする必要があるのですか?とにかく実際にポインターを取得しています(Cの関数に配列を渡すことはできません。関数のシグネチャに関係なく、配列はポインターに低下します)。発信者に入力の予想サイズを知らせるのに役立ちますが、それを超えると役に立ちません。彼らはすでにサイズを通過しているので、使用するだけです...

int myfunc(int arr[], size_t size) {
    // ...
}

または

int myfunc(int *arr, size_t size) {
    // ...
}
于 2012-08-30T21:57:46.890 に答える