はじめに
落ち着いて次のプログラムを見てほしい。
# include <stdio.h>
# define PRINT_TYPE(e)\
printf("typeof " #e " is ");\
printf(_Generic((e),\
char: "char\n",\
char*: "char*\n",\
int: "int\n",\
int*: "int*\n",\
double: "double\n",\
double*: "double*\n",\
default: "unknown\n"));
int main() {
char* a, b; // 注目するのはこの行です。bの型は何だろう?
PRINT_TYPE(a);
PRINT_TYPE(b);
}
型判定のために見慣れないマクロPRINT_TYPE
があるが流してほしい。型判定のために使ってみただけだ。
本題だがchar* a, b;
の行に注目してほしい。b
の型は何だろう?大事なことなので二度言った。
b
の型はchar*
であるべきだ。
しかし、b
の型はchar
になってしまう。
typeof
でa
の型を調べたらchar*
だった。
int main() {
char* a;
typeof(a) c; //typeofで調べたaとcの型はchar*
}
typeof
で型を調べたらchar*
になることから、昔からa
の型はchar*
と認識されていた。
typeof
キーワードはGNUコンパイラの独自拡張であるが、typeof
はいつ導入されたのだろうか?
GCC
をダウンロードできるミラーサイトを調べたところ、gcc-1.21
にあってgcc-0.9
にないことから、typeof
がリリース日の1988年5月1日までに導入されていたことがわかった。1988年の時点ですでにb
の型はchar*
と認識されていた。
C言語は1972年デニス・リッチーがベル研究所で開発した。
JavaScriptやCの成功を考えると、後方互換性は大事なんだなと思いました。多少欠陥があっても言語設計を直さないほうがいい。
まとめ
char* a, b;
におけるb
の型に疑問を覚えた。気づけたのはJavaScriptからTypeScriptへと学習を進め型の大切さを認識したためかもしれないと思った。
b
の型はchar
ではなくchar*
であるべきだ。
型設計に欠陥があると言えるが、直さないほうがいい。後方互換性が大事なので。