内容简介:最近上課的時候鬧了一個大笑話(而且那門課還是組合語言不是程式設計...)。我寫了下面這隻程式:很明顯,這程式沒有 include 任何 header file,理論上應該是要包含 stdio.h。在編譯的過程中,compiler 吐出了下面的test.c: In function ‘main’:
最近上課的時候鬧了一個大笑話(而且那門課還是組合語言不是程式設計...)。我寫了下面這隻程式:
int main() { printf( "Hello\n" ); return 0; }
很明顯,這程式沒有 include 任何 header file,理論上應該是要包含 stdio.h。在編譯的過程中,compiler 吐出了下面的 警告信息 ( 不是錯誤信息唷 ):
test.c: In function ‘main’:
test.c:3:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
printf( "Hello\n" );
^
test.c:3:5: warning: incompatible implicit declaration of built-in function ‘printf’
test.c:3:5: note: include ‘<stdio.h>’ or provide a declaration of ‘printf’
但是程式會動,還是可以印出 Hello 的字樣。為什麽?我這時候信誓旦旦的跟大家說,因為 printf 在 libc.so 裡面有,因此就算編譯的時候找不到,gcc 在連結 libc.so 的時候還是會看的到 printf ,所以這時候還是可以執行的。為了證明這件事情,我用 nm 去看一下編出來的 test.o
0000000000000000 T main
U puts
等一下, where is my printf ?? ...在學生面前要保持鎮定,大概 printf 在系統裡被改成 puts ... 然後再做實驗給同學看,這次換成利用 libm.so 的 pow 函式。
int main() { printf( "2^3 = %f\n", pow( 2.0,3.0 ) ); return 0; }
然後說,這時候應該一定會有警告,而且程式還跑不起來,因為沒有 link 到 libm.so (我可沒有 -lm 的選項啊)。結果 ... 居然可以跑 ... ?? Why?? 趕快用 nm 看一下
0000000000000000 T main
U printf
恩,printf 出來了,萬歲,但我的 pow 呢?發生什麽事了,而且還可以執行,當場在課堂上楞在那邊發呆。掰不下去以後決定承認自己的無知 ... 還影響到後面上課個進行(因為都在想這個問題 ...)。
追下去,才發現真正的理由,那就是 ... gcc 它作弊 。相關資料可以參考這個網頁: Other Built-in Functions Provided by GCC 。資料節錄如下:
GCC provides a large number of built-in functions other than the ones mentioned above. Some of these are for internal use in the processing of exceptions or variable-length argument lists and are not documented here because they may change from time to time; we do not recommend general use of these functions .
The remaining functions are provided for optimization purposes
.
With the exception of built-ins that have library equivalents such as the standard C library functions discussed below, or that expand to library calls, GCC built-in functions are always expanded inline
and thus do not have corresponding entry points and their address cannot be obtained
. Attempting to use them in an expression other than a function call results in a compile-time error.
簡單來說,gcc 內建了一堆函式而且不具有 symbol,在程式執行的時候他會直接以 inline 的方式去處理這些函式。所以根本就不會有 symbol 在那邊。要證明這件事情,我們可以使用 -fno-builtin 這個 option 來停用 gcc 的 built-in function。之後再來編編看剛剛的程式:
neokent@Banner /data/test/20181026 $ gcc -fno-builtin -c test2.c
test2.c: In function ‘main’:
test2.c:3:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
printf( "2^3 = %f\n", pow( 2.0, 3.0 ) );
^
test2.c:3:27: warning: implicit declaration of function ‘pow’ [-Wimplicit-function-declaration]
printf( "2^3 = %f\n", pow( 2.0, 3.0 ) );
^
neokent@Banner /data/test/20181026 $ gcc -fno-builtin test2.c -o test2
test2.c: In function ‘main’:
test2.c:3:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
printf( "2^3 = %f\n", pow( 2.0, 3.0 ) );
^
test2.c:3:27: warning: implicit declaration of function ‘pow’ [-Wimplicit-function-declaration]
printf( "2^3 = %f\n", pow( 2.0, 3.0 ) );
^
/tmp/cczfqITn.o: 於函式 main:
test2.c:(.text+0x2d): 未定義參考到「pow」
collect2: error: ld returned 1 exit status
可以看到,pow 現在找不到定義了。解決方式?當然就是把 -lm 以及 header file加上去囉。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。