[C99] 第11回 その他、細部のちがい

ここでは、他の回で採り上げなかったC++とC言語の細かなちがいについて解説します。

可変個の実引数を取る関数の仮引数並び

C++では、printf 関数のような可変個の実引数を受け取る関数の仮引数並びを次のように記述することができました。

int printf(const char* format ...);  /* エラー */

しかし、C言語では、必ず ... の前にコンマを記述する必要があります。

int printf(const char* format, ...);  /* OK */

言語結合は使えない

C++では、extern "C"やextern "C++"のような「言語結合」を指定することができました。しかし、C99にはこのような機能はありません。他言語のコーリングコンベンションにあわせるには、__pascal や __fortran のような独自拡張のキーワードを使うことが多いようです。

使用できる識別子

識別子に関しては、C++に比べてC99のほうが制約がゆるいこともあれば、逆に制約が厳しいこともあります。

識別子途中の二重下線

C++では、識別の先頭だけでなく、途中や末尾にも二重の下線が含まれていてはいけません(予約名になります)。しかし、C99では、先頭の二重下線は予約済み識別子になりますが、それ以外の場所に二重下線が含まれていても問題ありません。ただし、C++と共通で使用するヘッダファイルでは、C99ではよくてもC++ではダメですので、途中や末尾に二重下線を含む識別子を使ってはいけません。

C++のキーワード

C99にはないC++だけのキーワードは、C99では識別子として使うことができます。ただ、無用の混乱を招くおそれがありますので、そうした識別子の使用は避けたほうがよいでしょう。

bool, true, false, and, or, notなどの識別子は、C99では<stdbool.h>や<iso646.h>で定義されるマクロですので、それらのヘッダをインクルードしなければ、一般識別して使うこともできます。しかし、混乱を避けるためには、これらの識別子の使用も避けたほうがよいでしょう。

C99特有のキーワード

C99では、C90に対して、キーワードがいくつか追加されています。_Bool, _Complex, _Imaginary, _Pragma, inline, restrictがそうです。inlineはC++でもありますが、restrictはC++にはないキーワードなので要注意です。下線で始まるキーワードについては、C++では予約済み識別子ですので、もともと一般識別子としては使えなかったものですから、(正しい知識があるC++プログラマにとっては)問題になることはないでしょう。

識別子の有意文字数

C++では、内部および外部識別子の有意文字数としては 1024 文字まで保証されます。しかし、C99ではずっと制約が厳しく、内部識別子は 63 文字、外部識別子は 31 文字までです。内部識別子については、国際文字名でも1文字は1文字ですが、外部識別子の場合、\uFFFF以下の国際文字名は 6 文字、それ以外の国際文字名は 10 文字に数えられます。結果として、通常の日本語の外部識別子は 5 文字までしか保証されないことになります。

国際文字名

C++と同様、C99でも識別子に国際文字名を使うことができます。ただし、ソースコード上の多バイト文字が国際文字名に変換されることは、C++ほど明確に規定されているわけではありません。

代替字句

C++では、and, or, not, bitand, and_eqや、<%, %:などの代替字句を使うことができます。しかし、C99では、andやorのような代替字句はマクロとして<iso646.h>ヘッダで定義されます。また、<%や%:などの代替字句は二文字表記と呼ばれ、そのまま使うことができます。

条件演算子

C99とC++では、条件演算子の構文が微妙に異なります。具体的には、C++では、

logical-or-expression ? expression : assignment-expression

であるのに対して、C99では、

logical-OR-expression ? expression : conditional-expression

となっています。第3オペランドにコピー代入演算子や複合代入演算子を含む式を指定した場合、解釈が変わるので要注意です。

以下、未解説の相違点が見つかり次第、解説を追記する予定です。

この記事のトラックバックURL:

http://www.kijineko.co.jp/trackback/902