C語言函式隱式宣告(1)

2021-09-05 11:47:26 字數 4748 閱讀 7530

這段時間,在看中心後台服務軟體原始碼時發現,有很多自定義函式未經

宣告卻能在主程式中被呼叫,主程式中沒有包括上述函式的標頭檔案,我在各個目錄中也找不到上述函式的標頭檔案。這就奇怪了,連使用標準庫函式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的函式體而報錯。...