[迷信] 構造体のタグ名は下線で始める

C の場合、タグ名だけでは型名になれず、struct, union, enum を付けなければなりません。そのため、使い勝手を向上するために typedef 名を付けることが多いのではないでしょうか? 一方、C++ ではクラスや列挙体のタグ名だけで型名になりますので、そうした typedef 名はあまり使う機会がないかもしれません。

というわけで、C では次のような型定義がよく行われます。

typedef struct _FOO {
  ...
} FOO;

ところが、このコードの動作は未定義だということをご存知でしょうか? _FOO のように、下線(アンダースコア、アンダーバー)で始まり、下線または大文字が続く識別子は「予約済み識別子」です。予約済み識別子というのは、規格がライブラリに使うか、処理系が作業用または拡張用に使うために予約されている識別子で、それらをユーザープログラムで使用することはできません(使用した場合の動作は未定義です)。

未定義の動作ですから、実行時におかしな振る舞いをするかもしれませんし、コンパイル時にエラーになったり、コンパイラがフリーズしたりするかもしれません。そうはいっても、現実には問題ないだろうと思われるかもしれません。確かに、実際に問題に直面する機会は少ないのですが、多くの場合、この問題に直面するのは異なる環境(同じコンパイラの将来のバージョンを含む)に移植する際なのです。

仮に問題に直面しないとしても、わざわざ未定義の動作を引き起こすような記述をしなければならない理由は一切ありません。ゴキブリを 1 匹発見すると 100 匹はいるといわれますが、ソースコードの中にこのような記述が見つかると、他の箇所にも多数の怪しい箇所が存在すると考えた方がよいでしょう。

いずれにせよ、こうしたコードは百害あって一利無しです。多くの場合、typedef 名を付けるのであればタグ名は不要です。つまり、

typedef struct {
  ...
} FOO;

上のように記述すれば済むはずです。線形リストなど、自己参照構造体の場合にはタグ名が不可欠ですが、その場合は、

typedef struct FOO {
  ...
} FOO;

とでもしておけば十分です。タグ名と型名では名前空間が異なりますから、同じ名前を付けても衝突することがありません。C++ ではタグ名と型名の名前空間は分かれていませんが、C との互換性のために、上のような typedef 名を定義しても問題ないことになっています。ですから、C++ との互換性の面でも問題ありません。

予約済み識別子は、タグ名だけでなく、いろいろなところでうっかり使ってしまいがちです。何が予約済み識別子であるかのルールは結構煩雑ですので、下線で始まる識別子は一律使わないことに決めてしまった方が無難です。

命名にちなんで補足的な話を少々。 Bjarne

命名にちなんで補足的な話を少々。

Bjarne StroustrupによるC++のスタイルとテクニックに関するFAQ
http://www.libjingu.jp/trans/bs_faq2-j.html#Hungarian

 (マクロ以外に)"すべての文字を大文字にした名前(例: BEGIN_TRANSACTION)は、慣例的にマクロでの 使用に予約されているので、絶対に使用しないでください。"

 仕様にはなっていないはずですが、言語作者からすれば、マクロ以外の識別子に小文字のない名前を使用することはタブーです。例え列挙型やconst値でも使ってはいけません。
 ご存知だとは思いますが、マクロ同士の衝突では警告が発生しますが、マクロとそれ以外の識別子では衝突が検知されません。上手くコンパイルエラーになってくれれば幸いですが、例えばconst int XXX_LIMIT = 100;というような定数が、#define XXX_LIMIT 50 という形で上書きされると、バッファーオーバーランが発生するまで気づかない可能性もあり非常に危険です。

C++について追記ですが、global

C++について追記ですが、global namespaceにおいて aq_aq で始まる識別子はその後が大文字なのかによらず実装用に予約済みです。
なのでどこかのnamespace下なら問題ないでしょうが、using文が存在するのでusing ::boost::lambda::_1;のような使い方は未定義動作となります。
やはり使わないのが無難ですね。

typo

いつも興味深く拝読させていただいています。

先頭から2つ目の文、typoでしょうか。
typede名 → typedef名

Re:typo

ご指摘ありがとうございます。修正しておきました。

このエントリーを含むはてなブックマーク