2008-08

変数宣言の位置によってエラーになったりならなかったりする。(Visual C++ 6.0, C2275, C2146)

 ここ2〜3日の間、古いC言語のプログラム(1992年作!)を修正しているのですが、ちょっとおもしろいことがあったのでメモメモ。

 たとえばtest.cというファイル名で次のようなコードを書いたとする。

#include <stdio.h>

typedef void *HANDLE;

int main(void)
{
 printf("This is C++ like syntax with .c suffix.\n");
 int i;
 HANDLE h;

 return 0;
}


 これをCygwinのgccでビルドするとこうなる。

d:\Home>gcc test.c
gcc test.c

d:\Home>


 エラーは出ない。
 Visual C++ 6.0でビルドするとこうなる。

--------------------構成: test - Win32 Debug--------------------
コンパイル中...
test.c
D:\Home\test.c(8) : error C2143: 構文エラー : ';' が 'type' の前に必要です。
D:\Home\test.c(9) : error C2275: 'HANDLE' : typedef 識別子に、クラス メンバ アクセス演算子 (->) を使用しました。
D:\Home\test.c(3) : 'HANDLE' の宣言を確認してください。
D:\Home\test.c(9) : error C2146: 構文エラー : ';' が、識別子 'h' の前に必要です。
D:\Home\test.c(9) : error C2065: 'h' : 定義されていない識別子です。
cl.exe の実行エラー

test.exe - エラー 4、警告 0


 こうだと通る。

#include <stdio.h>

typedef void *HANDLE;

int main(void)
{
 int i;
 HANDLE h;
 printf("This is C++ like syntax with .c suffix.\n");

 return 0;
}


 ビルドすると…、

--------------------構成: test - Win32 Debug--------------------
コンパイル中...
test.c
D:\Home\test.c(8) : warning C4101: 'h' : ローカル変数は 1 度も使われません。
D:\Home\test.c(7) : warning C4101: 'i' : ローカル変数は 1 度も使われません。
リンク中...

test.exe - エラー 0、警告 2


 こうなる。
 警告は出るが、エラーは消える。

 あるいはファイル拡張子を.cから.cppに変更(test.c → test.cppにリネーム)してもエラーを消すことができる。

 この理由がわからなくてちょっと悩んだんですけど、調べてみると1999年12月1日にC言語がISO/IEC 9899:1999 - Programming Language C(略称 C99) として規格化されたときに仕様の変更があり、変更前の仕様だとエラーになり、変更後の仕様だとエラーにならないようです。

 http://seclan.dll.jp/c99d/c99d07.htm
 ↑
 こちらのURLを参考にしました。助かりました。「7.7 変数宣言と実行コードの位置関係」に詳しい解説があります。

まとめ:
・古い仕様だと変数の宣言はブロックの先頭(関数、if、elseなどの最初)で行う必要がある。
・新しい仕様だとその変数が実際に使用される前であればどこでも構わない。
・C++は新しい仕様と同様。今回の例だとtest.cをtest.cppとリネームするとC++だと認識されてエラーは出なくなる。

 古い仕様、新しい仕様、C++、いずれのやり方でビルドされるか? はコンパイラとコンパイルオプション、それからファイル拡張子で決まり、古いコンパイラだと古い仕様、新しいコンパイラでも古い仕様でビルドするオプションを指定すれば古い仕様、拡張子がcppだとC++のファイルだと認識され、C言語ライクな書き方をしてもエラーにはならないのではないかと思います。
(きちんと調べていません)

かわいらしい無限ループの書き方

ttp://pc11.2ch.net/test/read.cgi/prog/1177664788/

を偶然見つけて気に入ったもの:

#define _ 1

for (;_;) {
}


#define T_T 1

while (T_T) {
}


while ("無限ループ")


おもしろいな。ネタとしてもおもしろいけど、for文の;についてきちんと考えるのもおもしろい。

«  | HOME |  »

プロフィール

志田

Author:志田
どこにでもいるIT土方です。
詳細はこちらを。

最近の記事

最近のコメント

最近のトラックバック

月別アーカイブ

カテゴリー

ブログ内検索

RSSフィード

リンク

このブログをリンクに追加する

By FC2ブログ

今すぐブログを作ろう!

Powered By FC2ブログ

ブロとも申請フォーム

この人とブロともになる

QRコード

QRコード