次のコードは何をしていますか?
int g[] = {9,8};
int (*j) = g;
私の理解では、2つのintの配列へのポインターを作成しています。しかし、なぜこれが機能するのですか:
int x = j[0];
これは機能しません:
int x = (*j)[0];
あなたの例では、括弧は不要です。ポインターは、関連する配列があるかどうかを気にしません-intを指していることだけを知っています
int g[] = {9,8};
int (*j) = g;
のように書き換えることもできます。
int g[] = {9,8};
int *j = g;
これは次のように書き換えることもできます
int g[] = {9,8};
int *j = &g[0];
配列へのポインタは次のようになります
int g[] = {9,8};
int (*j)[2] = &g;
//Dereference 'j' and access array element zero
int n = (*j)[0];
このリンクには、ポインター宣言 (およびそれらを理解する方法) に関する良い読み物があります。
int g[] = {9,8};
これは int[2] 型のオブジェクトを宣言し、その要素を {9,8} に初期化します
int (*j) = g;
これは int * 型のオブジェクトを宣言し、g の最初の要素へのポインターで初期化します。
2 番目の宣言が j を g 以外のもので初期化するという事実は、かなり奇妙です。C と C++ には、配列に関する奇妙な規則があり、これもその 1 つです。ここで、式g
は、オブジェクト g を参照する左辺値から、gint*
の最初の要素を指す型の右辺値に暗黙的に変換されます。
この変換はいくつかの場所で発生します。実際に実行すると発生しますg[0]
。配列インデックス演算子は、実際には配列では機能せず、ポインターでのみ機能します。したがって、ステートメントがint x = j[0];
機能するのは、が初期化g[0]
されたときに行われたのと同じ暗黙的な変換がたまたま行われるためです。j
配列へのポインタは次のように宣言されます
int (*k)[2];
そして、あなたはこれがどのように使用されるかについて正確に正しいです
int x = (*k)[0];
( 「宣言は使用に従う」ことに注意してください。つまり、型の変数を宣言するための構文は、その型の変数を使用するための構文を模倣しています。)
ただし、通常、配列へのポインターは使用しません。配列に関する特別な規則の全体的な目的は、配列要素へのポインタを配列であるかのように使用できるようにすることです。そのため慣用的な C では、通常、配列とポインターが同じではないことを気にしません。この規則により、配列を直接使用して有用なことを行うことはほとんどできません。(たとえば、次のような配列をコピーすることはできませんint g[2] = {1,2}; int h[2]; h = g;
:)
例:
void foo(int c[10]); // looks like we're taking an array by value.
// Wrong, the parameter type is 'adjusted' to be int*
int bar[3] = {1,2};
foo(bar); // compile error due to wrong types (int[3] vs. int[10])?
// No, compiles fine but you'll probably get undefined behavior at runtime
// if you want type checking, you can pass arrays by reference (or just use std::array):
void foo2(int (&c)[10]); // paramater type isn't 'adjusted'
foo2(bar); // compiler error, cannot convert int[3] to int (&)[10]
int baz()[10]; // returning an array by value?
// No, return types are prohibited from being an array.
int g[2] = {1,2};
int h[2] = g; // initializing the array? No, initializing an array requires {} syntax
h = g; // copying an array? No, assigning to arrays is prohibited
配列は C および C++ の他の型と非常に矛盾しているため、避ける必要があります。C++ はstd::array
より一貫性があり、静的なサイズの配列が必要な場合に使用する必要があります。動的なサイズの配列が必要な場合、最初のオプションは std::vector です。
j[0];
へのポインターを逆参照するint
ため、その型はint
です。
(*j)[0]
タイプがありません。*j
へのポインターを逆参照するint
ため、 を返し、int
を(*j)[0]
逆参照しようとしint
ます。しようとしているようなものint x = 8; x[0];
です。