1

私はこのリンクを読んでいましたC++で配列を使用するにはどうすればよいですか?、セクション5。配列を使用する際の一般的な落とし穴。例は次のとおりです。

// [numbers.cpp]
int numbers[42] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

// [main.cpp]
extern int* numbers;
int main()
{}

numbers.cppの「numbers」は配列の名前であり、通常は「 &numbers [0] 」に等しいポインタに減衰する可能性があるため、main.cppでは「numbers」の値は「&numbers[0]」のままであると予想されます。 。しかし、違います!代わりに「numbers[0]」、つまり「1」です。

または、私がコンパイラであるとしましょう。「numbers.cpp」では、シンボル「numbers」が「1」を指すアドレスとして表示されます。なぜこの同じシンボルが「main.cpp」の値1に変更されるのですか?

私はそれが著者が「タイプ安全でないリンク」と言っていることを理解しています。しかし、コンパイラーがタイプミスマッチリンクエラーを発生させたとしても、コンパイラーがこれを行う理由はわかりません。

コメントコメント

私の理解では、コンパイラは以下を同等と見なしているので、リンカーは成功します。そうでない場合、「未解決の外部」エラーが発生します。

// [numbers.cpp]
int tmp[42] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; //{1,..9} starts at global address 0x1234
int *numbers = &tmp[0];                    //numbers == 0x1234

// [main.cpp]
extern int* numbers;                       //numbers == 0x1234
int main()
{}

実際の状況:

// [numbers.cpp]
int numbers[42] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; //{1,..9} starts at global address 0x1234

// [main.cpp]
extern int* numbers;                       //numbers == numbers[0] == 1
int main()
{}
4

3 に答える 3

2

それを説明する次の方法は役に立ちますか?

が配列の場合a(つまり、コンパイラがの型がa配列型であることを認識している場合)、構文a[i]は次のように解釈されます。配列のi番目の要素を返します。

一方、aがポインタ(配列の最初の要素への)である場合、同じ構文は次のa[i]ように解釈されます。に格納されているアドレスを検索しa、i要素に対応するバイト数を追加して、を返します。そこに保存されている値。

ではmain.cpp、それがnumbersポインタ(*)であると見なし、対応するアクションを適用します。つまり、に格納されている値numbersを検索し、それをアドレスとして扱い、バイト数を追加して、そのアドレスに格納されている値を返します。

(*)numbersそこでポインタとして宣言されているのでこれを行います。コンパイラは、それが実際に配列であることを認識しません。これは、とmain.cppは別にコンパイルされるためですnumbers.cpp(つまり、別の変換ユニットです)。したがって、配列をポインタに減衰させることはありません。単に、すでにポインタであると想定しているだけです。

于 2013-02-22T04:19:01.730 に答える
1

数値が配列の場合、たとえば。数字[]の場合、それが指すものを変更することはできません。オブジェクトファイルは、シンボル「numbers」を実際の配列{1、2、...}にマップします。ただし、numbersがポインタの場合、たとえば、* numbersの場合、それが指すものを変更できます。オブジェクトファイルは、シンボル「numbers」を単一のポインター値にマップします(それ自体が配列の先頭を指している場合がありますが、それはわかりません)。

配列とポインタは同じように機能しますが、同じものではありません。

于 2013-02-22T04:01:06.617 に答える
-3

C ++では、一般的な答えは「コンテナを使用する」です。配列のようなコンテナの場合、通常はstd::vectorが必要です。最大のパフォーマンスが必要な場合は、std :: valarrayの方が適している場合があります(もちろん、パフォーマンスは、gsliceなどで使用する目的のように使用した場合です)。

より良い記事は「C++でCスタイルの配列をいつ使用するか」です。回答:他のソフトウェアに接続する必要がない限り、ほとんどありません。

于 2013-02-22T04:02:23.000 に答える