C言語ってきもい?

たまには他所さまのプログラミング記事についても言及してみることにしましょう。今回取り上げるのは、ブログ「赤の他人」「C言語ってきもい」です。ここでは、下記のようなコードがあったとき、b() == c() が真にならない可能性はあるか? という問題を扱っています。

//a.c
int a(void){
  return 1;
}
int b(void){
  return a();
}
 
//b.c
int c(void){
  return a();
}

先方では、x86系CPU上で *(int*)a = 0xCCC3C033; とコードを書いた上で最大限の最適化をかけると、a.cではaがインライン置換されるので b() == c() が真にならない場合があると主張しています。確かにそういうこともあるでしょう。けれども、可能性だけを考えるのであれば、そんな話を持ち出すまでもありません。

まず、C99だと仮定した場合、暗黙的な関数宣言の仕様は廃止になっていますので、aを宣言せずに呼び出しているcの動作は未定義です。したがって、何が起きても不思議ではなく、可能性という意味では b() == c() が真にならないという現象もあり得ます。

次に、C99ではないと仮定した場合、// で始まるコメントはサポートされませんので、それを記述した場合の動作は未定義です。したがって、この場合にも何が起きても不思議ではありません。

さらに、実際に b() == c() が評価されている部分のコードが登場していないわけですから、これについては好きなように書くことができるとすれば...(*(int*)a = 0xCCC3C033; が許されるぐらいですから何でもありでしょう)

/* main.c */
#define b() 1
#define c() 0
int main(void)
{
  b() == c();
  return 0;
}

あるいは、

/* main.c */
static int b() { return 1; }
static int c() { return 0; }
int main(void)
{
  b() == c();
  return 0;
}

とすれば、当然 b() == c() は偽になりますし、

/* main.c */
double b();
char c();
int main(void)
{
  b() == c();
  return 0;
}

のようにしても、未定義の動作を引き起こし、偽になる可能性があります。

なお、今回は本当に"きもい"のは何かについてはあえて触れないことにします。たまには他所さまの記事に言及するのも悪くないので、今後もときどき挑戦したいと思います。

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

http://www.kijineko.co.jp/trackback/705
このエントリーを含むはてなブックマーク