C と C++ の両方で、は型指定子ではなく宣言*
子にバインドします。どちらの言語でも、宣言はオブジェクトではなく式の型に基づいています。
たとえば、int
名前付きへのポインターがあり、その値p
にアクセスしたいとします 。次のように、単項演算子でポインターを逆参照することでこれを行います。int
p
*
x = *p;
式 のタイプ*p
はint
; したがって、の宣言p
は
int *p;
これは、同じ宣言ステートメント内で宣言するポインターの数に関係なく当てはまります。q
およびr
もポインターとして宣言する必要がある場合は、宣言子の一部として単項も必要です*
。
int *p, *q, *r;
式 *q
と*r
型があるためint
です。T *p
、、T* p
またはT * p
; と書くことができるのは、C および C++ 構文の偶然です。これらの宣言はすべて として解釈されT (*p)
ます。
これが、ポインターと参照型を次のように宣言する C++ スタイルが好きではない理由です。
T* p;
T& r;
これは、C および C++ の宣言構文がどのように機能するかについて誤った見方をしていることを意味し、まさにあなたが経験したような混乱を招くからです。しかし、私は C++ を十分に書いてきたので、そのスタイルによってコードの意図が明確になる場合があることを理解できました。特にコンテナー タイプを定義する場合はそうです。
しかし、それはまだ間違っています。
T* p
これは (2 年遅れて) Lightness Races in Orbit への応答です (そして、私がこの規則を「間違っている」とラベル付けすることに反対する人は誰でも)...
まず第一に、これとまったく同じように、規則の使用と、それが人々の期待どおりに機能しないことから具体的に生じる多くの質問があります。このサイトには、「 と の両方をポインターとして宣言T* p
しないのはなぜですか?」という質問がいくつありますか?T* p, q
p
q
それは混乱をもたらします - それ自体でその使用を思いとどまらせるのに十分なはずです.
しかし、それ以上は一貫性がありません。宣言子から配列性または関数性を分離することはできません。なぜポインター性を分離する必要があるのでしょうか。
「それは、[]
and()
が後置演算子であり、 while*
が単項だからです」. はい、そうです。では、演算子をオペランドに関連付けないのはなぜですか? 宣言T* p
では、T
は のオペランドではない*
のに、なぜそうであるかのように宣言を書くのでしょうか?
a
が「ポインタの配列」である場合、なぜ と書く必要があるのでしょうT* a[N]
か? f
「ポインタを返す関数」の場合、なぜ と書く必要があるのでしょうT* f()
か? これらの宣言をおよびとして記述した場合、宣言子システムはより理にかなっていて、内部的に一貫性があります。これは、任意の型 (実際、宣言指定子の任意のシーケンス) の代用として使用できるという事実から明らかなはずです。T *a[N]
T *f()
T
そして、配列へのポインターと関数へのポインターがあり、宣言子1*
に明示的にバインドする必要があります。
T (*a)[N];
T (*f)();
はい、ポインター性は宣言するものの重要なプロパティですが、配列性と機能性も同様であり、一方を他方よりも強調すると、解決するよりも多くの問題が発生します。繰り返しますが、この質問が示すように、T* p
慣習は混乱を招きます。
*
は単項であり、それ自体が別のトークンであるため、 、 、 、および と書くことができます。T* p
これらT *p
はT*p
すべてT * p
コンパイラによって受け入れられますが、すべて として解釈されT (*p)
ます。さらに重要なことは、T* p, q, r
として解釈されT (*p), q, r
ます。と書くと、その解釈はより明白になりますT *p, q, r
。ええ、ええ、ええ、「1 行に 1 つだけ宣言すれば問題ありません」。他に問題にしない方法を知っていますか? 宣言子を適切に記述してください。宣言子システム自体がより理にかなっており、間違いを犯す可能性が低くなります。
私たちは言語の「アンティークの奇妙さ」について議論しているわけではありません。それは言語の文法とその哲学の基本的な構成要素です。ポインター性は、配列性や関数性と同様に宣言子のプロパティであり、混乱を招くだけでなく、C と C++ の両方を必要以上に理解するのが難しくなります。
逆参照演算子を後置ではなく単項にするのは間違いだと私は主張します2が、それが B でどのように機能したかであり、Ritchie はできるだけ多くの B を保持したいと考えました。T* p
また、Bjarne による大会の推進は誤りであると主張します。
- 議論のこの時点で、誰かが次のような typedef の使用を提案するでしょう。
typedef T arrtype[N];
arrtype* p;
これは要点を完全に見逃しており、「C: The Complete Reference」の初版は大きくて重く、他の何の役にも立たないため、提案者に打撃を与えています。
T a*[N]*()
とは対照的に、書くことT (*(*a)[N])()
は間違いなく目が疲れにくく、スキャンがはるかに簡単です。