web-dev-qa-db-ja.com

C / C ++ int []対int *(ポインター対配列表記)。違いはなんですか?

Cの配列は、順次格納されるデータへの単なるポインターであることを知っています。しかし、どのような違いが表記[]と*の違いを意味します。私はすべての可能な使用状況で意味します。例えば:

char c[] = "test";

この命令を関数本体で提供すると、スタックに文字列が割り当てられます

char* c = "test";

データ(読み取り専用)セグメントを指します。

これら2つの表記法のすべての違いをすべての使用状況で一覧表示して、明確な一般的なビューを形成できますか。

36

C99標準によると:

配列型は、要素型と呼ばれる特定のメンバーオブジェクト型を持つ、連続して割り当てられた空でないオブジェクトのセットを記述します。

36)配列型は、その要素型と配列内の要素の数によって特徴付けられます。配列型はその要素型から派生したと言われ、その要素型がTである場合、配列型はarray of Tと呼ばれることもあります。要素タイプからの配列タイプの構築は、配列タイプの派生と呼ばれます。

ポインタ型は、関数型、オブジェクト型、または参照型と呼ばれる不完全な型から派生する場合があります。ポインター型は、その値が参照される型のエンティティへの参照を提供するオブジェクトを記述します。参照型Tから派生したポインター型は、Tへのポインターと呼ばれることもあります。参照された型からのポインタ型の構築は、ポインタ型の派生と呼ばれます。

標準宣言によると…

char s[] = "abc", t[3] = "abc";
char s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };

…同一です。配列の内容は変更可能です。一方、宣言…

const char *p = "abc";

…pを定数charへのポインタとして定義し、初期化して、constant array of charC++)で、要素が文字列リテラルで初期化される長さ4。 pを使用して配列の内容を変更しようとした場合、動作は未定義です。

6.3.2.1Array subscriptingによると、逆参照と配列添字は同じです。

添え字演算子[]の定義は、E1[E2](*((E1)+(E2)))と同一であることです。

配列とポインターの違いは次のとおりです。

  • ポインタは、その背後にあるメモリサイズの情報を持ちません(それを取得するポータブルな方法はありません)
  • 不完全な型の配列は構築できません
  • ポインタ型は不完全な型から派生する場合があります
  • ポインターは再帰構造を定義できます(これは前の2つの結果です)

これらのリンクは主題に役立つかもしれません:

25
Sergey K.
char c[] = "test";

これにより、文字列テストを含む配列が作成されるため、任意の文字を変更/変更できます。

c[2] = 'p';

だが、

char * c = "test"

これは文字列リテラルであり、const charです。
したがって、この文字列リテラルを変更すると、セグメンテーション違反が発生します。そう

c[2] = 'p';

現在違法であり、セグメンテーション違反を引き起こします。

9
neel

_char []_は「charの不明な境界の配列」型を示し、_char *_は「charへのポインター」型を示します。ご覧のとおり、「charの未知の境界の配列」型の変数の定義が文字列リテラルで初期化されると、型は「array [N] of char」に変換されます。Nは適切なサイズです。同じことは、一般に配列集合体からの初期化にも当てはまります。

_int arr[] = { 0, 1, 2 };
_

arrは「int [の配列[3]」型に変換されます。

ユーザー定義の型定義(structclassまたはunion)では、C++で不明なバインド型の配列は禁止されていますが、Cの一部のバージョンではlast構造体のメンバーとして許可され、構造体の終わりを超えて割り当てられたメモリにアクセスするために使用できます。この使用法は「柔軟な配列」と呼ばれます。

再帰型の構築も別の違いです。 _char *_(たとえば_char **_、char (*)[10])へのポインタと配列を作成できますが、これはバインドされた未知の配列には違法です。 _char []*_または_char [][10]_を書くことはできません(char (*)[]と_char [10][]_は問題ありません)。

最後に、cv-qualificationの動作は異なります。 _typedef char *ptr_to_char_および_typedef char array_of_unknown_bound_of_char[]_が与えられた場合、ポインターバージョンのcv修飾は期待どおりに動作しますが、配列バージョンのcv修飾はcv修飾を要素タイプに移行します。つまり、_const array_of_unknown_bound_of_char_架空のchar (const) []ではなく_const char []_と同等です。これは、プロトタイプを作成する前に配列からポインターへの減衰が引数に作用する関数定義では、

_void foo (int const a[]) {
    a = 0;
}
_

合法です; array-of-unknown-boundパラメーターを変更不可にする方法はありません。

4
ecatmur

ポインタ変数を宣言しても変数の型が作成されないことを指し、ポインタ変数を作成します。

そのため、実際には、文字列が必要な場合は、文字の配列を指定する必要があり、ポインターは後で使用できます。

1
Shash

実際には、配列は定数ポインターと同等です。

また、char c []は、ベースアドレスがcである配列にメモリを割り当てます。そのアドレスを保存するための個別のメモリは割り当てられません。

Char * cを書き込むと、ベースアドレスがcに格納されている文字列にメモリが割り当てられます。また、cの格納には別のメモリロケーションが使用されます。

0
Cygnus