2012年11月29日 星期四

gcc編譯相同內容之.c/.cc但執行結果不同

我一直很傻很天真的以為,gcc會把我餵給他的所有東西都編譯成C程式,直到我膝蓋中了一箭,直到昨天我才發現這個世界不是我所想像的樣子。

我從2005年開始學習C程式設計卻一直到昨天才知道這件事情實在有點慚愧,不過長知識了也算是開心。(是說我會直接在Terminal下gcc也是2007年底的事情了)

原來gcc會看餵進去的檔案的副檔名來推斷檔案應該是個C程式還是C++程式,然後編譯之,這樣好像有點強......


事情是這樣的,昨天我在Plurk上看到強者我同學AZ大大plurk了一則plurk,內容是轉載Jserv大大的一篇網誌,說sizeof這個function在C和C++中會有不同的表現,身為一個資訊工程學學士,應該要富有實驗與驗證的精神,於是我便想寫程式來確認一下,我寫了下面這隻小程式:


#include <stdio.h>
int main(){
    char q = 'q';
    printf("%d %d %d\n",sizeof('q'),sizeof(q),sizeof(char));
    return 0;
}

然後按照過去的習慣,我認為所有的程式碼通過gcc都會編譯成C程式,就下了指令:

$ gcc sizeof.cc -o gcc_sizeof_cc。
$ ./gcc_sizeof_cc
1 1 1
咦,Jserv大大的網誌不是說結果應該會是4 1 1嗎?所以我就想說會不會因為.cc其實是C++附檔名的關係,所以就複製了一下。
$ cp sizeof.cc sizeof.c
$ gcc sizeof.c -o gcc_sizeof_c
$ ./gcc_sizeof_c
4 1 1
咦,這樣就是C程式應該跑出的結果,可是gcc不是都會把東西編成C嗎?真是令人好奇,然後我就
$ man gcc
看一下gcc的文件,終於在970行附近看到了以下的段落:
 Compiling C++ Programs
       C++ source files conventionally use one of the suffixes .C, .cc, .cpp,
       .CPP, .c++, .cp, or .cxx; C++ header files often use .hh, .hpp, .H, or
       (for shared template code) .tcc; and preprocessed C++ files use the
       suffix .ii.  GCC recognizes files with these names and compiles them as
       C++ programs even if you call the compiler the same way as for
       compiling C programs (usually with the name gcc).

       However, the use of gcc does not add the C++ library.  g++ is a program
       that calls GCC and treats .c, .h and .i files as C++ source files
       instead of C source files unless -x is used, and automatically
       specifies linking against the C++ library.  This program is also useful
       when precompiling a C header file with a .h extension for use in C++
       compilations.  On many systems, g++ is also installed with the name
       c++.

       When you compile C++ programs, you may specify many of the same
       command-line options that you use for compiling programs in any
       language; or command-line options meaningful for C and related
       languages; or options that are meaningful only for C++ programs.

天啊!這真是太神奇了,原來gcc會認這是C還是C++,如果是誤入迷途的C++檔案他就會把他當成C++來編譯(However, the use of gcc does not add the C++ library.) 。至於g++就是都拿去當C++編譯沒錯,可以實驗如下:
$ g++ sizeof.c -o g++_sizeof_c
$ g++ sizeof.cc -o g++_sizeof_cc
$ ./g++_sizeof_c
1 1 1
$ ./g++_sizeof_cc
1 1 1
如果你想要把這些會被認成是C++的.cxx檔案以gcc編譯成C程式該怎麼做呢?其實只要加上參數x指定語言即可:
$ gcc -x c sizeof.cc -o gcc_x_c_sizeof_cc
$ ./gcc_x_c_sizeof_cc
4 1 1
這樣就編譯成C語言的程式了。

最後要感謝我的強者同學群柏崴大大、AZ大大還有阿蹦大大等諸位大大的討論與指教,感謝。