日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

能否用痰盂盛饭——谈谈在头文件中定义外部变量

發布時間:2024/4/14 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 能否用痰盂盛饭——谈谈在头文件中定义外部变量 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

能否用痰盂盛飯——談談在頭文件中定義外部變量 - garbageMan - 博客園

能否用痰盂盛飯——談談在頭文件中定義外部變量

?  “能否用痰盂盛飯”并非是一個技術問題,而是一個哲學問題。
哲學問題沒有標準答案,只存在不同的選擇。
有一種觀點認為,痰盂可以盛飯。理由是只要不漏能把飯吃到嘴里就行。我看這個理由任何人都無法反駁。
另有一種觀點認為,痰盂是用來吐痰的,不可以用來盛飯。他們覺得用痰盂盛飯是一種不可理喻的行為。然而這種看法可能會被“痰盂派”視為一種不必要的潔癖。

C語言中也有類似的“痰盂”問題:

頭文件除了可以包含函數原型和宏定義外,也可以包括結構體類型定義和全局變量定義
————譚浩強,《C程序設計》(第四版)學習輔導,清華大學出版社,2010年7月,p188

在頭文件中究竟能否定義外部變量呢?這個問題同樣有兩種選擇。
“痰盂派”會認為可以。比如
在 abnormal.h 中寫

int e_v = 1 ;

?

然后在abnormal.c中寫

#include "abnormal.h" #include <stdio.h> int main(void) {printf("%d\n",e_v);return 0; }

沒有人會說這段源程序有什么語法問題,它也沒有違背C語言的任何規定。就像痰盂可以用于盛飯是一個道理。
但是,“非痰盂派”會覺得這段源程序透著一種莫名其妙的詭異:既然定義變量e_v是為了在abnormal.c中使用,那么把這個變量定義在abnormal.c中顯然最直接也最便利,為什么要舍近求遠地把它定義到abnormal.h文件中呢?
在“非痰盂派”的眼中,“*.h”文件不是用來寫變量定義的,就如痰盂不是用來盛飯的一樣。那么“*.h”文件是做什么用的呢?
首先來看最簡單的情況

?
#include <stdio.h>#include <math.h>int main(void){??printf("%f\n",sqrt( 9.0 ));??return 0;}

?

?  在這段代碼中,出現了printf和sqrt這樣兩個標識符,由于編譯器在編譯時不認得這兩個標識符,所以需要告訴編譯器這兩個標識符的含義。這就是代碼前面兩條預處理命令

?
#include <stdio.h>#include <math.h>

的意義。這兩個頭文件中分別包含printf和sqrt這樣兩個標識符的類型聲明。只有告訴了編譯器這兩個標識符的含義,編譯器才能把它正確地編譯成目標文件(*.obj或*.o)。(如果函數返回值類型為int可不聲明,但這是一種落后的、逐漸被淘汰的風格)
所以“*.h”文件的一個基本功能就是提供函數類型聲明。
另外要注意到的一點是,stdio.h、math.h是由庫函數作者提供的,相當于給其他模塊提供了一個使用“說明書”,使用庫函數的模塊用這個“說明書”向編譯器說明自己所用到的在其他模塊定義的函數名的數據類型。
下面舉例進一步說明。
假設一個源程序由兩個*.c源文件組成,第一個*.c提供求兩個double類型數據和的函數,第二個使用這個函數。那么,第一個*.c文件的作者僅僅寫出
1.c

?
double add(double d1,double d2){??return d1 + d2 ;}

?

是遠遠不夠的,因為這個1.c雖然可以編譯目標文件(*.obj或*.o)以供連接時使用,但是在鏈接之前,2.c文件在編譯時還需要告訴編譯器add這個標識符的含義,否則無法正確地編譯出與之相應的目標文件。為此,第一個*.c文件的作者還應該給出一個“說明書”——*.h文件
1.h

?
double add(double,double);

?

?  2.c文件可以寫為

?
#include "1.h"int main(void){??printf("%f\n",add(3.0,4.0));??return 0;}

這樣就解決了第二個*.c文件的編譯問題(add得到了說明)。
需要說明的是,在很多情況下1.c自己也往往需要包含這個1.h文件,因為這個1.c中可能有其他函數也需要調用這個add()函數,因而也需要這個函數類型聲明。所以一般1.c寫為
1.c

?
#include "1.h"double add(double d1,double d2){??return d1 + d2 ;}

?  再來看*.h文件中出現數據類型聲明的情況。
假設在1.c中使用了一種新的用戶定義的數據類型(不一定是“結構體類型”),例如

?
typedef double DOUBLE;

這時通常也應該把該數據類型的聲明寫在“*.h"文件中提供給其他模塊,除非這個類型僅僅在1.c中使用。
這時的1.h應該為
1.h

?
typedef double DOUBLE;DOUBLE add(DOUBLE,DOUBLE);

?  這時的1.c為
1.c

?
#include "1.h"DOUBLE add(DOUBLE d1,DOUBLE d2){??return d1 + d2 ;}

?  而2.c則為

?
#include "1.h"int main(void){??DOUBLE d1=3.0,d2=4.0;??printf("%f\n",add(d1,d2));??return 0;}

?  在這里共有兩處用到了DOUBLE類型,一次是定義d1,d2這兩個變量,另一次是調用add()函數。由于在1.h中這種類型已經得到了聲明,所以這段代碼可以順利通過編譯。
除了函數類型聲明、數據類型聲明出現在*.h文件中,宏定義也可能出現在*.h中。
如果1.c和2.c都需要一個共同的常數,把這常數作為一個符號常量寫在1.h中,顯然可以避免你寫你的、我寫我的,從而造成大家不協調一致的錯誤。因為這時大家都是在參照著同一個常數(宏)在寫代碼。
但是,如果把外部變量的定義寫在*.h中會出現什么情況呢?很顯然,會出現在1.c和2.c中兩次定義這個外部變量的情況,這是絕對不允許的。這就是“非痰盂派”認為在頭文件中不可以寫外部變量定義的理由。

總結

以上是生活随笔為你收集整理的能否用痰盂盛饭——谈谈在头文件中定义外部变量的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。