web-dev-qa-db-ja.com

配列c ++へのポインター

次のコードは何をしていますか?

int g[] = {9,8};
int (*j) = g;

私の理解から、2つのintの配列へのポインターを作成します。しかし、なぜこれが機能するのですか:

int x = j[0];

これは機能しません:

int x = (*j)[0];
20
Sam Adamsh

この例では、括弧は不要です。ポインターは、配列が含まれているかどうかを気にしません-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];

次のリンクで、ポインター宣言(およびそれらをどのように理解するか)をよく読んでいます: http://www.codeproject.com/Articles/7042/How-to-interpret-complex-CC-declarations =

40
Ben Cottrell
int g[] = {9,8};

これは、int [2]型のオブジェクトを宣言し、その要素を{9,8}に初期化します

int (*j) = g;

これは、int *型のオブジェクトを宣言し、それを初期化しますgの最初の要素へのポインターを使用

2番目の宣言がjをg以外の何かで初期化するという事実はかなり奇妙です。 CとC++には配列に関するこれらの奇妙なルールがあり、これもその1つです。ここで、式gは、オブジェクトgを参照する左辺値から、gの最初の要素を指すint*型の右辺値に暗黙的に変換されます。

この変換はいくつかの場所で発生します。実際、g[0]を実行すると発生します。配列インデックス演算子は実際には配列では機能せず、ポインタでのみ機能します。したがって、ステートメントint x = j[0];は、g[0]jの初期化時に行われたのと同じ暗黙の変換を行うために機能します。

配列へのポインタは次のように宣言されます

int (*k)[2];

そして、あなたはこれがどのように使用されるかについて正確に正しいです

int x = (*k)[0];

(注: "declaration following use" 、つまりdeclaringの構文は型の変数に似ていますsingその型の変数に似ています)

ただし、通常は配列へのポインターを使用しません。配列に関する特別な規則の全体的な目的は、配列要素へのポインターを、あたかも配列であるかのように使用できるようにすることです。したがって、一般的な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です。

22
bames53

j[0];intへのポインターを逆参照するため、そのタイプはintです。

(*j)[0]にはタイプがありません。 *jintへのポインターを逆参照するため、intを返し、(*j)[0]は、intの逆参照を試みます。 int x = 8; x[0];

9
Luchian Grigore