這段時間,在看中心後台服務軟體原始碼時發現,有很多自定義函式未經
宣告卻能在主程式中被呼叫,主程式中沒有包括上述函式的標頭檔案,我在各個目錄中也找不到上述函式的標頭檔案。這就奇怪了,連使用標準庫函式printf()都要包括標準輸入輸出標頭檔案,何況是自定義函式?這個問題困擾了我很久。前天問中創公司奚鍾華,他說:確實沒有標頭檔案,
他也試過,在原來的目錄中編寫了一些新的函式,照葫蘆畫瓢地在makefile中新增了相應項,生成了庫檔案,在主程式中就可呼叫了,其中的機理
他也說不清。
今天通過實驗,基本明白了
其中原因。
一、在vc6中,檔案test1.cpp如下:
#include "stdafx.h" // stdafx.h: #include int max(int x, int y)
int main(int argc, char* argv)
程式正常執行,因為max()在被呼叫前已經定義。
將max()移到main()之後:
#include "stdafx.h" // stdafx.h: #include int main(int argc, char* argv)
int max(int x, int y)
編譯時出錯:
error c2065: 'max' : undeclared identifier
error c2373: 'max' : redefinition; different type modifiers
在main()之前新增max()的宣告:
#include "stdafx.h" // stdafx.h: #include int max(int x, int y);
int main(int argc, char* argv)
int max(int x, int y)
程式正常執行,因為max()在被呼叫前已經定義。
二、在linux中,檔案test2.c如下:
#include int max(int x, int y)
int main(int argc, char* argv)
用gcc編譯:gcc -wall -o test2 test2.c,通過。程式正常執行,因為max()在被呼叫前已經定義。
將max()移到main()之後:
#include int main(int argc, char* argv)
int max(int x, int y)
用gcc編譯:gcc -wall -o test2 test2.c,出現警告:
warning: implicit declaration of function `max'
仍然編譯通過,程式也能正常執行,因為
在c語言中,當函式在呼叫函式之前沒有宣告或定義,預設作為隱式宣告處理
,只要在呼叫函式之後定義,或在別的模組中定義並編譯成庫檔案,該庫檔案在呼叫函式所屬模組編譯時載入,程式即可正常執行。
用g++編譯:g++ -wall -o test2 test2.c,出現錯誤和警告:
error: `max' was not declared in this scope
warning: unused variable 'max'
沒有生成可執行程式test2。因為g++使用c++的規則:函式在被呼叫前必須宣告或定義。
三、在linux中,採用實際工程的方式(分成若干模組)進一步實驗,驗證了
c語言中函式在被呼叫前不宣告也能使用。
1、在/u01/work/tools目錄中,編寫4個檔案:
max.c:
int max(int x, int y)
min.c:
int min(int x, int y)
add.c:
int add(int x, int y)
makefile:
#user defined library
cc=gcc
home=/u01/work
os=$(home)/tools
include=$(home)/headfile -i$(home)/tools
cstargets=max.o min.o add.o
libs=$(home)/lib/tools.a
all: $(libs) clean
max.o : max.c
$(cc) -i$(include) -c $(ccflags) max.c
min.o : min.c
$(cc) -i$(include) -c $(ccflags) min.c
add.o : add.c
$(cc) -i$(include) -c $(ccflags) add.c
$(libs) : $(cstargets)
cd $(os); /
ar ruv $(libs) $(cstargets:$home/lib/=)
clean:
rm -f *.o
在/u01/work/tools目錄中,使用make工具:
[root@node01 tools]# make
gcc -i/u01/work/headfile -i/u01/work/tools -wall -c max.c
gcc -i/u01/work/headfile -i/u01/work/tools -wall -c min.c
gcc -i/u01/work/headfile -i/u01/work/tools -wall -c add.c
cd /u01/work/tools; /
ar ruv /u01/work/lib/tools.a max.o min.o add.o
r - max.o
r - min.o
r - add.o
rm -f *.o
生成了/u01/work/lib/tools.a庫檔案。
2、在/u01/work/test2目錄中,編寫2個檔案:
test2.c:
#include int main(int argc, char* argv)
makefile:
cc=gcc
home=/u01/work
include=-i$(home)/headfile -i.
cflags= -l$(home)/lib
libs=$(home)/lib/tools.a
all : $(objs) test2 clean
test2 : test2.c
$(cc) $(include) -wall -o test2 test2.c $(cflags) $(libs)
clean :
rm -f *.o
在/u01/work/test2目錄中,使用make工具:
[root@node01 func_pointer]# make gcc -i/u01/work/headfile -i. -wall -o test2 test2.c -l/u01/work/lib /u01/work/lib/tools.a
test2.c: in function `main':
test2.c:11: warning: implicit declaration of function `max'
test2.c:12: warning: implicit declaration of function `min'
test2.c:13: warning: implicit declaration of function `add'
rm -f *.o
生成了/u01/work/test2/test2可執行檔案。執行程式:
[root@node01 func_pointer]# ./test2
please input 2 integer (a, b):
200300
max(a, b): 300
min(a, b): 200
add(a, b): 500
結果完全正確。
四、小結
c和c++是
強型別語言,變數型別均應在**執行前確定。
在函式宣告方面c和c++則不同,c++語言中,在被呼叫之前未宣告或定義是不允許的,而c語言是允許的。初看起來c語言這一特性是靈活、省事,但缺點是:
1、程式可讀性差。
2、易出錯。函式先宣告再呼叫,是一種糾錯機制,
如果不宣告,則沒有用到這種糾錯機制
(不能進行引數、返回值型別檢查)
,雖然編譯、連線通過,程式也能執行,但很可能結果不正確。
乙個好的程式設計師,應該養成嚴謹、規範的程式設計習慣,編譯程式時應開啟顯示所有警告選項「-wall」,並且對編譯器提出的所有警告都要給予處理,僅以編譯、連線通過為目標,這可能會有潛在的危害。
C語言函式隱式宣告(2)
1 什麼是c語言的隱式函式宣告 在c語言中,函式在呼叫前不一定非要宣告。如果沒有宣告,那麼編譯器會自動按照一種隱式宣告的規則,為呼叫函式的c 產生彙編 下面是乙個例子 int main int argc,char argv 單純的編譯上述源 並沒有任何報錯,只是在鏈結階段因為找不到名為any nam...
C語言中的隱式函式宣告
1 什麼是c語言的隱式函式宣告 在c語言中,函式在呼叫前不一定非要宣告。如果沒有宣告,那麼編譯器會自動按照一種隱式宣告的規則,為呼叫函式的c 產生彙編 下面是乙個例子 1 2 3 4 5 int main int argc,char argv 單純的編譯上述源 並沒有任何報錯,只是在鏈結階段因為找不...
C語言中的隱式函式宣告
在c89中,函式在呼叫前不一定非要宣告。如果沒有宣告,那麼編譯器會自動按照一種隱式宣告的規則,為呼叫函式的c 產生彙編 下面是乙個例子 int main int argc,char ar 單純的編譯上述源 並沒有任何報錯,只是在鏈結階段因為找不到名為any name function的函式體而報錯。...