目次

ヘッダ内の関数プロトタイプ宣言

引数

 ANSIに準拠した処理系のヘッダ中における関数プロトタイプ宣言は、引数の先頭に「__」(アンダースコアが2つ)が付いていることがある。

例:

double sin(double __x);

 ユーザーが定義するマクロ名と重複してしまう可能性を避けるためにアンダースコアが付いている。1つではなく2つ付いている理由は、ANSIではアンダースコア1つで始まる名前は処理系が独自の目的で使用する可能性がある。そのため、2つにしているのである。

[補講]関数プロトタイプ宣言では、必ずしも引数名を記述する必要はない。

例:

double sin(double);

ヘッダの重複定義

 同じヘッダファイルを2回以上インクルードしても問題ない。わざと2回インクルードすることはないと思うが、知らない間に2回以上インクルードされていることはありえる。  例えば、abc.hの中でmax.hをインクルードしているのを忘れて、abc.hとmax.hの2つをインクルードする状況が考えられる。関数や変数の重複があれば、再定義エラーが出て問題に気付くかもしれない。  しかし、マクロの場合は同じ名前のマクロを何度定義してもよいので、エラーが出ない。つまり、max.hの中でmaxマクロを定義してあり、abc.h(中でmax.hをインクルードしている)とmax.hの2つをインクルードする状況である。

 こうした問題を回避するためには、ヘッダファイルに次のようなコードを含めておけばよい。

#if !defined(__MAX)
 #define __MAX
 #define max(a,b) ((a) > (b) ? (a) : (b))
#end if

 初めてこのヘッダをインクルードした場合は、マクロ名__MAXは未定義なので、2〜3行目で__MAXと関数形式マクロのmaxが定義される。一方、2回目以降のインクルードのときには、1行目の条件式が成り立たないため、再定義されない。

演算子の結合規則

 同一の優先順位を持つ演算子が複数個並んだときに、左右どちらの演算を優先的に計算するかを表すことを結合規則(associativity)という。

 ここで2項演算子を◎としたとき、a ◎ b ◎ cを考える。

  • 左結合
    • 「(a ◎ b) ◎ c」と解釈される。
    • 例えば、-(マイナス)演算子など。
  • 右結合
    • 「a ◎ (b ◎ c)」と解釈される。
    • 例えば、代入演算子(=)など。

応用

例1

 ptrをポインタ変数とする。このとき、次の関係が成り立つ。ただし、「=」は代入演算子ではなく、ここでは等号を意味する。

++*ptr = ++(*ptr) = (*ptr)++ ≠ *ptr++

 なぜならば、*演算子と++演算子は同一の優先順位を持ち、右結合だからである。

参考文献

  • 『C言語プログラミングの落とし穴』