22

Cでポインターを宣言する場合、次の3つのバリエーションがあります。

バリアントA:

int* ptr;

バリアントB:

int *ptr;

バリアントC:

int * ptr;
  • Aでは、間接演算子が型に追加されています。
  • Bでは、間接演算子が変数の前に追加されています。
  • Cでは、間接演算子は型と変数の間に自由に存在します。

ポインタの宣言方法は、読んだドキュメントの種類によって異なります。一部の作者は特定の亜種を好むようですが、他の作者はいくつかを使用しています。

  • 異なるバリアント間で機能に違いはないと仮定するのは正しいですか?
  • はいの場合、Cでどのバリアントを使用する必要があるかについての規則はありますか?
4

8 に答える 8

19

他の誰も言及していないことはそれです

int *ptr;

言語文法により密接に対応します。

  • int *ptr;宣言であり、次のもので構成されます。
    • 宣言指定子intその後に続く
    • 宣言者、*ptr

(これは実際にはいくつかのステップをスキップしますが、基本的な考え方は理解できます。)

宣言は使用に続くので、これが意味するのは*ptrタイプintです。これからptr、タイプが続きますint*

これはより良いものになると主張することができます

int* ptr;

同じ理由で

x = y+z;

よりも良い

x=y + z;

もちろん書くことができます

int* ptr;

ptrそしてそれを「タイプ」と読みますint*。そして、多くのプログラマーはまさにそれを実行し、うまくやっています(C ++で好まれるスタイルになる傾向があります)。コンパイラーはあなたがどちらの方法でそれを行うかを気にしません、そしてあなたのコードを読んでいる人はどちらの方法でもそれを理解するのに苦労するべきではありません。

しかし、どの間隔を選択する場合でも、int *ptr;実際に何を意味するのかを理解する必要があります。

int *ptr, i;

他の誰かのコードでは(必然的にそうなるでしょうが)、それptrがポインターでiあり、intであることがすぐにわかります。

また、プロジェクトで他のプログラマーと協力している場合は、コーディング標準にある既存の規則に従う必要があります。規則がない場合は、コードが既に記述されている方法に従う必要があります。私は個人的には好きint *ptr;ですint* ptr;が、両方のスタイルを組み合わせて使用​​することは、どちらか一方を一貫して使用するよりもはるかに悪いです。

于 2012-01-20T21:19:50.920 に答える
14

機能性に全く違いはありません

int* ptr;

int *ptr;

どちらを使用するかはあなた次第です。選択できる競合するコーディングスタイルは複数あります。

于 2012-01-20T20:11:36.867 に答える
11

同じ行に同じタイプの複数の変数を宣言する場合にのみ重要です。たとえば、複数のintポインターが必要な場合は、次のようにする必要があります。

int *a, *b, *c;

ただし、スタイル的には、単一の変数のみを宣言している場合、これは混乱を招きます。多くの人は、型の後に変数名が続くのを見たいと思っています。型はintではなくintへのポインターであると想定されているため、次のことを好みます。

int* a;
int* b;
int* c;

ある形式を他の形式よりも優先するかどうかは、最終的にはあなた次第です。Cを専門的にプログラミングしてきた20年間で、約50%の人がどちらか一方を選択するのを見てきました。

于 2012-01-20T20:13:41.763 に答える
11
T *a;

TKernighan&RitchieのCに関する本、およびISO / IEC 9899:2018で使用されているように、ポインタを宣言するための推奨されるCスタイルです。

T* a;

TStroustrupのC++に関する本で使用されているように、ポインタを宣言するための推奨されるC++スタイルの方法です。

両方の表記法は同等です。

于 2012-01-20T21:16:10.847 に答える
9

それらは両方とも他の人が言ったのと同じ意味です。しかし、あなたを待っている罠があります。このコードを考えてみましょう:

int* a, b;

あなたはこれがへのポインタを宣言したと思うかもしれませんint。そうではありませんが、そうではありません。実際aはそうですint*bですint*これは、多くのCプログラマーが型ではなく変数の横に置くことを好む理由の1つです。このように書かれたとき:

int *a, b;

aあなたは何であるかについて誤解される可能性が低くなりますb

そうは言っても、多くのコーディング標準では、1行に1つだけの変数を宣言するように求められています。

int* a;
int b;

行ごとに1つの変数のルールに従う場合、混乱の余地はありません。

于 2012-01-20T20:46:34.730 に答える
4

C宣言は、オブジェクトではなく、のタイプに基づいています。

int名前付きのへのポインタがあり、piそれが指す整数値にアクセスする場合は、次のようにポインタを逆参照する必要があります。

x = *pi;
printf("%d", *pi);
*pi = 1 + 2;

など。式のタイプ *pi次のintとおりです。したがって、宣言は次のように読み取る必要があります。

int *pi;

charここで、 ;へのポインタの配列があると仮定しましょう。任意の文字に到達するには、最初に配列に添え字を付けてから、結果を逆参照する必要があります。

c = *pc[i];
if (*pc[j] == 'a') {...}

繰り返しますが、式のタイプは *pc[i]charあるため、宣言は次のようになります。

char *pc[N];

*piとは両方とも宣言*pc[N]子として知られており、型指定子によって指定されていない追加の型情報を指定します。IOW、の配列とポインタは宣言子の一部として指定され、-nessは型指定子によって指定されます。 pcchar

どちらのスタイルが適切かという質問については...

どちらも「正しい」わけではありませんが、私(および他の多くのCプログラマー)は、言語文法(宣言子の一部)をより厳密に反映し、複数の項目を宣言するときの混乱を避けるのに役立つため、ではT *pなく書くことを好みます。私は、ポインターになることを 書いたり期待したりする人々の例をあまりにも多く見ました。T* p*T* a, b;b

その批判に対する通常の反応は、「1行に複数の項目を宣言しないでください」です。その回答に対する私の回答は、「宣言者を正しく記述すれば問題はない」というものです。

このスタイルを好む多くのC++プログラマーの間には異なる考え方があり、コードを読みやすくする ことができるT* p場合がいくつかあります(C ++に限定されます) 。

ただし、これは次の単純なポインターに対してのみ機能しTます。ポインターの配列、配列へのポインター、関数へのポインター、関数へのポインターの配列へのポインターなどを処理し始めると、パラダイムは急速に崩壊します。つまり、何かを書くことです。お気に入り

T* (*(*p)[N])(); // p is a pointer to an array of pointers to functions
                 // returning pointers to T.

混乱した思考を示しているだけです。ただし、パラダイムに従わなければならないことを本当に本当に感じている場合は、いつでも一連のtypedefを作成できます。T* p

編集

もう一度試してみましょう。

typedef T* TPtr;                           // pointer to T
typedef TPtr TPtrFunc();                   // function returning pointer to T
typedef TPtrFunc* TPtrFuncPtr;             // pointer to function returning
                                           // pointer to T
typedef TPtrFuncPtr TPtrFuncPtrArray[N];   // N-element array of pointer to function
                                           // returning pointer to T

TPtrFuncPtrArray* p;

神の愛のために、そうしないでください。

于 2012-01-20T22:33:29.170 に答える
1

Cでは、トークンを区切るために必要な場所を除いて、空白は重要ではありません。両方のバリアントは構文的に正しいです。

バリアント1は、ポインター演算子をタイプに関連付けます。これは十分に論理的です。私にとって、Variant 2が理にかなっている理由がなければ、それで十分でしょう。

バリアント2は、C宣言の構造と一致しています。C文法では、ポインター演算子は、型ではなく、宣言子(つまり、名前)に属します。これは、同じ宣言で複数の変数を宣言する場合に重要です。それが重要な、より難解なケースもいくつかあります。

したがって、私にとって、バリアント2はCとより一貫性があります。しかし、どちらのバリアントも防御可能であり、両方のバリアントは従来型です。

于 2012-01-20T20:18:20.457 に答える
0

あなたは正しいです、どちらもコンパイラにとってまったく同じことを意味します。どちらのステートメントも、型の変数を生成します(int *)

どちらが正しいか:ワームの缶!それは通常、討論のトピックです。会社やOSSで働いている場合は、定義されたコーディングスタイルに従うのがおそらく最善です。ない場合は、通常、コードベースのこの部分で明らかに使用されているスタイルに一致するLNT(トレースを残さない)スタイルを使用します。

読者にとっては理解しやすいと言えます。たとえば、タイプについて話していることをより明確に伝えるものにint* ptr;近づけ*ます...int(int *)

于 2012-01-20T20:16:17.253 に答える