補足(いいわけ?)002


宣言の中の*(2001/3/29)

先日(一昨日かな)、とある方に教えていただいたのですが、 あの「2ちゃんねる」に「C言語 ポインタ完全制覇」 に関するスレッドができていますね(^^;

http://mentai.2ch.net/test/read.cgi?bbs=prog&key=983870222
http://mentai.2ch.net/test/read.cgi?bbs=prog&key=982225911

なんかいろいろ言われてますが、私は生まれてこの方「2ちゃんねる」に 書き込みをしたことはただの一度もありません。 もちろん存在は以前から認識していましたが、 そう熱心な読者というわけでもありません。 たまに人に「こんなスレッドがあるよ」とか教えてもらって読む程度です。

というわけで、私が『「2ちゃんねらー」か?』と言われればおそらくNoでしょう (「2ちゃんねらー」の定義はよく知りませんが...)。 また、上記のスレッドが著者の自作自演ではないかという疑いについては はっきり否定しておきます。んなこたしませんって(^^; まあ、それを証明する手段はないですけど。

で、それはさておき、 スレッドの中でちょっと補足しておこうかと思う話題がありましたので。

本の方ならp.143に以下の文章があります。

まず、この文には嘘があります
宣言の中の*, (), []は演算子ではないですし、優先順位も、 構文規則の中で演算子とは別の箇所で定義されています。

「配列とポインタの完全制覇」 にも同等の文があります。

で、「2ちゃんねる」の方では、宣言の中でも*や()は[]は演算子ではないか、 と主張する人がいるわけです。これに対する私の見解を書きます。

Cのトークンには、キーワード(keyword)、識別子(identifier)、 定数(constant)、文字列リテラル(string-literal)、 演算子(operator)、区切り子(punctuator)があります(6.1)。

んで、6.1.5には演算子の一覧が載っていまして、 その中には *や()や[]はもちろん入っています。

ただし、6.1.6の「区切り子」を見ると、

区切り子:次のいずれか
  [ ] ( ) { } * , : = ; ... #

となっています。

()については、ifの後ろなどでも使うのでそっちのことだと解釈することも 可能ですが、[]や*は、式の中で出てくる明らかに演算子な奴を除けば、 宣言の中以外では登場しないはずです(コメントでも/* */のように*を使うけど、 これはトークンではない)。

よって、宣言の中の*や[]や()は、「区切り子」に分類されているわけで、 「演算子」ではない、と私は認識していますが...

# もしかして間違ってましたらご指摘ください(_o_)

JIS X3010 「6.1.5 演算子」の意味規則の所には以下の記述があることですし。

演算子は、値を生成すること、指示子を生成すること、副作用を引き起こすこと、 又はそれらの組み合わせの操作[評価(evaluation)]を指定する。

「2ちゃんねる」の方では「宣言子演算子」という言葉が出てきていますけど、 この言葉は確かに「プログラミング言語C++ 第3版」のp.115に出てますが、 Cにはこんな用語はないはずです。

私はC++の規格書は持っていないのですが、 「プログラミング言語C++ 第3版」p.115のBNFによれば、 確かに宣言の中の*はptr-operatorになってますね。

ただし、CのBNF(K&Rならp.296)のそれに相当する部分には、 単にpointerと書いてあるだけです。

ちなみにですが、ISO C99では、トークンの種類が

  token:
      keyword
      identifier
      constant
      string-literal
      punctuator

となっていて、6.4.6 Punctuatorsで、 普通の演算子もぞろぞろといっしょくたに提示されていますが、 そこで、

Depending on context, it may specify an operation to be performed (which in turn may yield a value or a function designator, produce a side effect, or some combination thereof) in which case it is known as an operator(other forms of operator also exist in some contexts).

と書いてあるから、同じでいいんじゃないかな、と思うんですが、どうでしょう?

# いずれにせよ、K&Rも「C 言語ポインタ完全制覇」もISO C99は
# 対象にしていないわけですが。

で、K&Rですが、

まさかKernighanやRitchieが上記の規格を知らないはずはないでしょう。 ただ、入門書ではわかりやすくするために嘘を書くことはよくあることです。

K&Rのこの文章↓を見ると、

ここで * は前置演算子であり、() より低い優先度を持つから、 正しい結合を行なわせるにはカッコが必要なのである。

演算子の優先順位でもって宣言の結合の優先度を説明しようとしているようです。

こういうのは説明上の方便としてアリかとは思いますが、 *私には* やっぱり混乱を招いているだけのように見えます。 現実に宣言の構文は演算子の優先順位とは全く別に規定されているわけですから。


「補足(いいわけ?)」の目次に戻る | ひとつ前のページ | ひとつ後のページ | 「C言語 ポインタ完全制覇」のページに戻る | トップページに戻る