web-dev-qa-db-ja.com

ポインター宣言でのアスタリスクの配置

私は最近、C/C++を最終的に学習する必要があると判断しましたが、ポインターについて、またはより正確には、その定義について本当に理解していないことが1つあります。

これらの例はどうですか:

  1. int* test;
  2. int *test;
  3. int * test;
  4. int* test,test2;
  5. int *test,test2;
  6. int * test,test2;

さて、私の理解では、最初の3つのケースはすべて同じことをしています。テストはintではなく、intへのポインターです。

2番目の例のセットはもう少し複雑です。ケース4では、testとtest2の両方がintへのポインターになりますが、ケース5ではtestのみがポインターであるのに対し、test2は「実際の」intです。ケース6はどうですか?ケース5と同じですか?

84
Michael Stum

4、5、6は同じもので、testのみがポインターです。 2つのポインターが必要な場合は、以下を使用する必要があります。

int *test, *test2;

または、さらに良い(すべてを明確にする):

int* test;
int* test2;
119
Milan Babuškov

アスタリスクの周りの空白には意味がありません。 3つすべてが同じことを意味します。

int* test;
int *test;
int * test;

int *var1, var2 "は、単に人々を混乱させることを意図した悪意のある構文であり、避けるべきです。

int *var1;
int var2;
42
Ates Goral

"Clockwise Spiral Rule" を使用して、C/C++宣言の解析を支援します。

次の3つの簡単な手順があります。

  1. 未知の要素から始めて、スパイラル/時計回りの方向に移動します。次の要素に遭遇した場合、それらを対応する英語のステートメントに置き換えます。

    [X]または[]:Array X size of ...またはArray undefined size of ...

    (type1, type2):戻り値type1およびtype2を渡す関数...

    *:へのポインター.

  2. すべてのトークンがカバーされるまで、これをスパイラル/時計回りに続けてください。
  3. 必ず最初に括弧内の何かを解決してください!

また、可能な場合、宣言は別のステートメントで行う必要があります(ほとんどの場合に当てはまります)。

33
Michael Burr

多くのコーディングガイドラインでは、1行に1つの変数のみを宣言することを推奨しています。これにより、この質問をする前に持っていた種類の混乱を避けることができます。私が一緒に働いたほとんどのC++プログラマーはこれに固執しているようです。


ちょっとしたことは知っていますが、有用だと思うのは宣言を逆読みすることです。

int* test;   // test is a pointer to an int

これは、特にconstポインターの宣言を開始し、ポインターがconstであるかどうか、またはポインターが指すものがconstであるかどうかを知るのが難しい場合、非常にうまく機能し始めます。

int* const test; // test is a const pointer to an int

int const * test; // test is a pointer to a const int ... but many people write this as  
const int * test; // test is a pointer to an int that's const
31
Scott Langham

他の人が述べたように、4、5、および6は同じです。多くの場合、人々はこれらの例を使用して、*は、タイプではなく変数に属します。スタイルの問題ではありますが、次のように考えて記述すべきかどうかについては、いくつかの議論があります。

int* x; // "x is a pointer to int"

またはこの方法:

int *x; // "*x is an int"

FWIW私は最初のキャンプにいますが、他の人が2番目の形式について議論する理由は、それが(ほとんど)この特定の問題を解決するからです:

int* x,y; // "x is a pointer to int, y is an int"

誤解を招く可能性があります。代わりに、あなたはどちらかを書くでしょう

int *x,y; // it's a little clearer what is going on here

または、2つのポインターが本当に必要な場合は、

int *x, *y; // two pointers

個人的には、行ごとに1つの変数に保持すると言いますが、どのスタイルを好むかは関係ありません。

12
huskerchad
#include <type_traits>

std::add_pointer<int>::type test, test2;
11
fredoverflow

4、5、6では、testは常にポインターであり、test2はポインターではありません。 C++では、空白は(ほとんど)重要ではありません。

5

私の意見では、タイプではなく、アスタリスクをポインター名の隣に置く方が良いと思います。例:

int *pointer1, *pointer2; // Fully consistent, two pointers
int* pointer1, pointer2;  // Inconsistent (because only the first one is a pointer, the second one is an int variable), unexpected, and thus prone to errors

なぜ2番目のケースに矛盾があるのですか?なぜならint x,y;は同じ型の2つの変数を宣言しますが、型は宣言で1回だけ言及されます。これにより、前例のある予想される動作が作成されます。そしてint* pointer1, pointer2;は、pointer1ポインタとして、ただしpointer2は整数変数です。明らかにエラーが発生しやすいため、回避する必要があります(タイプではなく、アスタリスクをポインター名の隣に配置することにより)。

3
deLock

ポインターは、型の修飾子です。アスタリスクがどのようにタイプを変更するかをよりよく理解するために、それらを右から左に読むのが最善です。 「int *」は「inter to to int」と読むことができます。複数の宣言では、各変数がポインターであるか、標準変数として作成されることを指定する必要があります。

1,2および3)テストのタイプは(int *)です。空白は関係ありません。

4,5および6)テストのタイプは(int *)です。 Test2はint型です。繰り返しますが、空白は重要ではありません。

1
Ron Warholic

Cの理論的根拠は、変数を使用する方法で宣言することです。例えば

char *a[100];

*a[42]charになります。そしてa[42] charポインター。したがって、aはcharポインターの配列です。

これは、元のコンパイラライターが式と宣言に同じパーサーを使用したかったためです。 (言語設計の選択のあまり賢明な理由ではありません)

0
Michel Billaud

最初の慣例では、スターをポインター名側(宣言の右側)に置くことでした

あなたは同じルールに従うことができますが、タイプ側に星をつければ大したことではありません。 consistencyが重要であるため、どちらの側を選択したかに関係なく、常に同じ側の星を忘れないでください。

0
TheDrev

4、5、および6は次のように考えることができます。型の宣言は一度だけ行う必要がありますが、その型へのポインターを宣言する場合(アスタリスクを追加することにより)、変数ごとに宣言する必要があります。

ポインター変数を宣言するとき、1行に複数宣言している場合でも、変数とアスタリスクの間に常に空白を追加します。そうしないと、ほとんど毎回参照解除式と混同されます。

0
dxh