CとC++のIdent

今日、妙な話を聞いた。CかC++かでコードを書いていたところ、変数名を長くすると32文字だかそこらでtruncateされてしまい、前半が同じ名前の変数を使っているとコンパイルエラーになってしまったというのだ。私は(少なくともC++で)変数名に文字数制限があるとは思っていなかったので、かなり驚いた。むしろコンパイラを疑った。

というわけで規格書にあたってみることにした。C規格としてN1256(C99)を、C++規格はN3337(C++11)を参照する。

まず、Cでは§6.4.2.1の Language Lexical elements > Identifiers > General > Implementation limits に、

an implementation may limit the number of significant initial characters in an identifier ... Any identifiers that differ in a significant character are different identifiers. If two identifiers differ only in nonsignificant characters, the behavior is undefined.

との記述がある。要するに、処理系は識別子の最初の何文字か以降は無視してしまって構わないということだ。そしてもし無視されない前半部分が重複していて無視される後半部分のみが違う識別子の組が登場した場合、その挙動は未定義となる。

これは驚きだ。識別子として使える(意味を持つ)文字数は処理系定義なのか。ここしか見ていないのでわからないが、もしかしてこの文字数は1文字でも規格準拠なのだろうか……標準ライブラリのほとんど全てが使えないが。

ちなみにGCCでは文字数に制限はない(以下参照)。まあそりゃそうだ。

Using the GNU Compiler Collection (GCC): Identifiers implementation


ではC++ではどうだろう。§2.11のLexical convensions > Identifiersには、

An identifier is an arbitrarily long sequence of letters and digits.

と書かれている。任意の長さが許されるようだ。話が終わってしまった。まあ、安心するべきことではある。

まとめると、Cを書いている時に長い変数名を使って妙なことが起きた場合(そしてそれが純粋に変数名が長いことによる問題だった場合)、コンパイラが悪いとは言えない。しかしもしC++で識別子の後半が無視された場合は、コンパイラが悪い。プログラマは自信を持ってIssueを報告して構わないということだ。