7

ご存知のように、配列名を割り当てることはできません。次のような文です。

char * array[], * point;
array = point; /* wrong */
array++; /* wrong */

しかし、main(int argc, char * argv[])では、argv++問題なく、うまく機能します。何が欠けていますか?

4

3 に答える 3

6

あなたの例arrayでは真の配列であるため、変更できない左辺値です。main では、パラメーター リストで宣言されているため、argv実際にはchar **、つまり変更可能なポインターです。

要するにchar *array[]、文脈によって意味が異なるということです。

于 2012-11-21T19:26:51.060 に答える
5

関数パラメーター宣言のコンテキストでは、T a[]とは両方とも;T a[N]として解釈されます。T *a3 つのケースすべてで、 の配列ではなく、へのポインタaとして宣言されます。したがって、 inは、へのポインタの配列ではなく、 、または へのポインタへのポインタとして実際に宣言されます。 TTint main(int argc, char *argv[])argvchar **charchar

(編集-- これは、関数パラメーター宣言の場合にのみ当てはまることに注意してください。通常の変数宣言の場合T a[N]T a[]両方ともaの配列として宣言しTます)。

ポインタ値なので代入、インクリメントが可能です。

それを超えて、言語標準が言わなければならないことは次のとおりです。

5.1.2.2.1 プログラムの起動

... 2 それらが宣言されている場合、メイン関数の パラメーター
は次の制約に従うものとします
。プログラムの起動と終了の間。
argcargvargv

編集

関数パラメーターの言語は次のとおりです。

6.7.6.3 関数宣言子 (プロトタイプを含む)

... 7 ''
の配列'' としてのパラメータの宣言は、''への修飾ポインタ'' に調整され ます。キーワードが配列型派生のand内にも現れる場合、関数の呼び出しごとに、対応する実引数の値によって、少なくともサイズで指定された数の要素を持つ配列の最初の要素へのアクセスが提供されます。表現。 []static[]

編集2

いくつかの例 (C99 コンパイラを想定):

void foo(int a[], size_t len)
{
  size_t i;
  printf("sizeof a = %zu\n", sizeof a);
  printf("sizeof (int *) = %zu\n", sizeof (int *));
  for (i = 0; i < len; i++)
    printf("a[%zu] = %d\n", i, *a++);
}

int main(void)
{
  int a1[5] = {0};
  int a2[]  = {0, 1, 2, 3, 4};

  printf("sizeof a1 = %zu\n", sizeof a1);
  printf("sizeof a2 = %zu\n", sizeof a2);

  foo(a1, sizeof a1 / sizeof a1[0]);
  foo(a2, sizeof a2 / sizeof a2[0]);

  return 0;
}

標準語のもう 1 つの部分:

6.3.2.1 左辺値、配列、および関数指定子

... 3演算子、演算子、または単項演算子
のオペランドであるか、配列の初期化に使用される文字列リテラルである場合を除き、 ''の配列'' 型を持つ式は式に変換されます配列オブジェクトの最初の要素を指し、左辺値ではない「型へのポインター」を使用します。配列オブジェクトにレジスタ ストレージ クラスがある場合、動作は未定義です。 sizeof_Alignof&

関数mainでは、a1a2の 5 要素配列として宣言されていますinta2イニシャライザの要素数からサイズを取得します。したがって、これらの は「の 5 要素配列」の型を持ち、代入式のターゲットにすることも、or演算子のオペランドにすることもできません。これらの式が への呼び出しに現れると、それらの型は上記のルールに従って「へのポインタ」に変換されます。したがって、配列値ではなくポインター値を受け取ります(これは、配列パラメーターがポインター型に変換されるという規則によってカバーされます)。したがって、の式には type 、またはへのポインターがありますa1a2int++--foointfooaafooint *int; したがって、aは代入のターゲットである可能性があり、 および のオペランドである可能性が++あり--ます。

もう 1 つの違い: 上記の規則に従って、配列式が演算子のオペランドである場合、ポインター型への変換は行われませんsizeofsizeof a1配列が占めるバイト数a1(5 * sizeof int) に評価される必要があります。ただし、ainfooは typeであるため、int *notは(sizeof )へのポインターのバイト数にのみ評価する必要があります。 int [5]sizeof aint(int *)

于 2012-11-21T19:49:19.150 に答える
2
main(int argc, char * argv[])

また

main(int argc, char **argv)

同じで正しいです。関数の引数配列では、ポインターに減衰するためです

詳細については、これを読んでください

しかし、あなたが示したコードは実際の配列です。配列の名前は最初の要素のアドレスを示し、変更できないため、これを実行します。

 array = point; 
array++;

あなたがすでに述べたように間違っています。

于 2012-11-21T19:39:00.227 に答える