外部變量和外部函數

C程序由一組對象組成,這些對象包括程序中所使用的變量和實現特定功能的函數。變量可以分為函數內部定義、使用的變量和函數外部定義的變量,通常情況下,把函數內部定義、使用的變量稱為內部變量或局部變量,而將在函數外部定義的、供許多函數所使用的變量稱為外部變量,一般情況下,也可以稱為全局變量。

  由于C語言不允許在一個函數中定義其他函數,因此函數本身是外部的。一般情況下,也可以說函數是全局函數。在缺省情況下,外部變量與函數具有如下性質:所有通過名字對外部變量與函數的引用(即使這種引用來自獨立編譯的函數)都是引用的同一對象(標準中把這一性質稱為外部連接)。

  由于外部變量是可以全局訪問的,這就為在函數之間交換數據提供了一種可以替代函數變元欲返回值的方法。任何函數都可以用名字來訪問外部變量,只要這個名字已在某個地方做了說明或定義。如果要在函數之間共享大量的變量,那么使用外部變量要比使用一個長長的變元表更方便、有效。然而,也可能導致程序在各個函數之間產生太多的數據聯系。

  外部變量的用途還表現在它們比內部變量有更大的作用域和更長的生存期。內部自動變量只能在函數內部使用,當其所在函數被調用時開始存在,當函數退出時消失。而外部變量是永久存在的,他們的值在從一次函數調用到下一次函數調用之間保持不變。因此,如果兩個函數必須共享某些數據,而這兩個函數都互不調用對方,那么最為方便的是,把這些共享數據作為外部變量,而不是作為變元來傳遞。

1、外部變量的定義和使用

  根據C語言標準,在程序的所有源文件中,外部變量只能被定義一次,否則會導致重復定義的編譯錯誤。

1.1 外部變量的定義與聲明

  變量聲明用于通報變量的性質(主要是變量的類型),而變量定義則除此之外還引起存儲分配。如果在函數的外部包含如下說明:
  1. int? ? VarDesc;
  2. char? ? ? ?? ?Array[MAXVAL];
復制代碼
那么這兩個說明定義了外部變量VarDesc與Array,并為之分配存儲單元,同時也用作供源文件其余部分使用的說明。另一方面,如下兩行:
  1. extern??int? ? VarDesc;
  2. extern??char? ? ? ?? ?Array[];
復制代碼
為源文件剩余部分聲明了VarDesc是一個int 類型的外部變量,Array是一個char數組類型的外部變量(數組大小在其他地方確定),但這兩個聲明并沒有建立變量或為它們分配存儲單元,其中關鍵字extern表明該外部變量在其他地方被定義。

  根據C語言標準,外部變量雖然只能在某個文件中定義一次,但其作用域則是從其聲明處開始一直到其所在的被編譯的文件的末尾。因此其他文件可以通過extern說明來訪問它。

1.2 外部變量的使用方式

  如果外部變量被不同的函數所引用,并且這些函數沒有集中在一個源文件中,而是分布在不同的源文件中,那么函數在引用這些外部變量時,必須采取先聲明再使用的方式,否則,在編譯時會導致重復定義的編譯錯誤。

  若在多個文件的多個函數中引用外部變量,就需要在這些函數中重復聲明外部變量。這種方式可以解決編譯問題,但是代碼不夠簡潔。因此,在實際的編程中,大都采取了將外部變量統一定義在一個C源文件中,這個C源文件一般被稱為global.c,然后在對應的頭文件中,一般為global.h,聲明外部變量,最后在需要引用外部變量的源文件中使用#include "global.h"的方式,函數就可以引用所有的外部變量。因此,一般情況下,global.c內容為:
  1. #include "global.h"? ? ? ?

  2. /* for example, define two vars */
  3. int? ? VarDesc;
  4. char? ? ? ?? ?Array[MAXVAL];
  5. /* other external var define */
復制代碼
在對應的global.h頭文件的內容則為:
  1. #ifndef _GLOBAL_H? ?/* please insure _GLOBAL_H unique */
  2. #define _GLOBAL_H? ?/* avoid quotation iterativly */

  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif? ?/*__cplusplus */

  6. /* for example, declare two vars */
  7. extern??int? ? VarDesc;
  8. extern??char? ? ? ?? ?Array[];

  9. /* other external vars declaration */

  10. #ifdef __cplusplus
  11. }
  12. #endif??/* __cplusplus */

  13. #endif? ? ? ? /* _GLOBAL_H */
復制代碼
此外,在實際的編程中,這兩個文件頭部還應當有公司copyright聲明、文件功能說明、版本說明、創建、修改歷史等。

2、函數的定義和使用

  根據C語言標準,函數只能被定義一次,而且在函數中,不能再定義函數,因此函數本身是外部的。

2.1 函數的定義與聲明

  定義函數是給出函數體的函數描述。一個函數只有在聲明之后才能被引用。函數聲明中,需給出函數名、返回類型、參數列表等。

  函數的作用域從其聲明處開始一直到其所在的被編譯的文件的末尾,如果一個函數在定義之前就要使用到,或者這個函數定義在與所要使用它的源文件不相同的源文件中,那么就需要在使用該函數前,使用關鍵字extern聲明該函數,但由于函數默認是external的,因此函數聲明前的extern可以省略,這也是標準庫函數的頭文件中,函數聲明前沒有extern的原因,但在實際的編程中,一般不推薦這樣做,應當在函數聲明前加上extern。

2.2 函數的組織和使用

  如果某個函數需要引用另一個函數,則需要在引用該函數前聲明被引用的函數,否則可能會導致函數未定義錯誤。

  為了避免被引用函數的重復聲明和方便函數的引用,在實際的編程之中,采用在對應的頭文件中,統一聲明函數的方式。需要引用某一個函數時,只需要在該函數的定義源文件中包含被引用函數的頭文件即可。

  在實際的編程中,在頭文件中聲明函數,即聲明函數原型,在對應的C源文件中,定義函數及其實現代碼。因此,函數說明的頭文件內容和格式為:
  1. #ifndef _FUNCNAME_H? ?/* please insure _ FUNCNAME _H unique */
  2. #define _ FUNCNAME _H? ?/* avoid quotation iterativly */

  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif? ?/*__cplusplus */

  6. /* for example, declare functions */
  7. extern??int? ? func (int, int, int);
  8. /* of course, maybe declare functions like below
  9. * int? ? func (int, int, int);
  10. */
  11. /* other functions declaration */

  12. #ifdef __cplusplus
  13. }
  14. #endif??/* __cplusplus */

  15. #endif? ? ? ? /* _ FUNCNAME _H */
復制代碼
而在對應的C源文件內容為:
  1. #include " funcname.h"

  2. /* for example, define two vars */
  3. int? ? func (int a, int b, int c)
  4. {
  5. ? ? ? ? ? ? ? ? // functions body
  6. }

  7. /* other functions define */
復制代碼
在實際的函數頭文件和定義文件中還應當包含相應的頭文件等,以及公司copyright聲明、文件功能說明、版本說明、創建、修改歷史等。對于具體的函數,還應當有函數說明、輸入參數說明、返回說明、例外等。

3、靜態外部變量和函數

  如果某外部變量和函數僅供它們各自所在的源文件中的函數使用,而不能被其他函數訪問,那么就必須使用static關鍵字定義外部變量和函數。static說明適用于外部變量與函數,用于把這些對象的作用域限定為被編譯源文件的剩余部分。通過外部static對象,可以把一些外部變量和函數隱藏在某個源文件中,使得這些外部變量和函數僅僅可以被該源文件使用和共享,但不能被該源文件之外的函數所引用。

  另外,static說明也可以用于說明內部變量。內部靜態變量就像自動變量一樣局部于某一個特定函數,只能在該函數中使用,但與自動變量不同的是,不管其所作函數是否被調用,它都是一直存在的,而不像自動變量那樣,隨著所在函數的調用與退出而存在與消失。換而言之,內部靜態變量是一種只能在某一特定函數中使用的但一直占據存儲空間的變量。

  一般情況下,為保證靜態外部變量和函數能夠被本源文件的函數所引用,需要在該源文件的所有函數之前定義靜態外部變量和函數。那么,該C源文件的內容為:
  1. #include “funcname.h”? ? ? ?

  2. /* for example, define one static external var and one static function */
  3. static? ?int VarName = 0;
  4. static? ?int function (int a)
  5. {
  6. ? ? ? ? ? ? ? ? // function body
  7. }
  8. /* other static vars and functions */

  9. /* for example, define one function */
  10. char? ? ? ?? ?func (char*, char)
  11. {? ? ? ? ? ? ? ?
  12. ? ? ? ? ? ? ? ? VarName = 5;
  13. ? ? ? ? ? ? ? ? function (VarName);
  14. ? ? ? ? ? ? ? ? // other function body
  15. }

  16. /* other functions define */
復制代碼




外部變量,變量定義在其他文件中全局變量
extern可以置于變量或者函數前,以表示變量或者函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其他模塊中尋找其定義。


C語言外部變量的使用以及extern的用法

C語言的外部變量的定義和引用對初學者來說,是個難點.

對外部變量的說明和定義不是一回事.對外部變量的說明,只是聲明該變量是在外部定義過的一個全局變量..在這里引用.而對外部變量的定義,則是要分配存儲單元.一個全局變量只能定義一次,卻可以多次引用.

用extern聲明外部變量,目的是可以在其它的文件中調用.具體使用見下面的例子:

??????????????? file1.c?????????????????????????????????????????????????????? file2.c

??????? int i,j;//定義全局變量??????????????????????????????? extern?? int i,j;//外部變量說明

??????? char c;??????????????????????????????????????????????????????? extern char c;

?????? void func()??????????????????????????????????????????????????? void func1()

???? {???????????????????????????????????????????????????????????????????? {

???????? }??????????????????????????????????????????????????????????????????? }

在file2.c中對外部變量i,j,c進行了說明,就可以直接調用file1.c中定義的全局變量了

靜態變量static的使用

有時在中斷程序中定義了變量,不希望每次進入中斷程序,變量就被賦初值.這時就要使用static變量.靜態局部變量在編譯時賦初值,既只賦初值一次.見下例:

void serial_interrupt() interrupt 4 using 3

{ static uchar i="0";

?? i++;

}

上例中,編譯時,i被賦初值0,以后每進入一次中斷,i+1,而不是每次進入中斷,i都被請零,再加1

如果在a.c中要調用在b.c中定義的函數func(),需要在a.c中聲明該函數,表示該函數在別的源文件中定義。函數是可以互相調用的,因此函數都具有外部存儲種類的屬性。原則上調用一個在在本程序模塊文件以外的其他模塊文件所定義的函數,必須用關鍵字extern說明被調用函數是一個外部函數。實際使用中可以省掉extern。即下面兩個函數聲明沒有明顯的區別:

extern int f();和int f();

例如;

#include "2.h"
extern int a;
int _tmain(int argc, _TCHAR* argv[])
{
?test();
?printf("%d\n",a);
?
?return 0;
}

?

#include "2.h"
?int a;
int test()
{
?a=10;
?return 0;
}

//結果a=10;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254741.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254741.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254741.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

gulp中使用babel-polyfill編譯es6拓展語法

今天想在新項目中使用es6的generators,發現雖然gulp已經有了babel編譯,但仍會報錯,網上查找后發現解決辦法是加載polyfill,但是找到的辦法都不試用我的項目。 解決辦法:在index.html中加載node_modules的babel-polyfil…

CoDeSys

CoDeSys是全球最著名的PLC內核軟件研發廠家德國的3S(SMART,SOFTWARE,SOLUTIONS)公司出的一款與制造商無關的IEC 61131-1編程軟件。CoDeSys 支持完整版本的IEC61131標準的編程環境,支持標準的六…

使用halcon結合機械XY軸對相機進行9點標定

小哥哥小姐姐覺得有用點個贊唄! 先在halcon中計算仿射變換矩陣并驗證 //在圖像中找到的模板中心位置 PicX:[1680.721,2065.147,911.499,526.798,1290.920,1285.731,1300.953] PicY:[968.321,964.366,976.283,980.035, 587.055,394.727,1355.487] //與圖像中查找…

Ubuntu Linux 提出新的發布模式——測試周

2019獨角獸企業重金招聘Python工程師標準>>> 導讀開源技術項目最大的優勢之一就是社區的每個人都可以自由地提出想法,如果獲得社區支持,它可以變成現實。著名的 Ubuntu 開發人員 Simon Quigley 就提出了一個可能改變 Ubuntu Linux 開發過程的…

264 I和IDR

I和IDR幀都是使用幀內預測的。它們都是同一個東西而已,在編碼和解碼中為了方便,要首個I幀和其他I幀區別開,所以才把第一個首個I幀叫IDR,這樣就方便控制編碼和解碼流程。IDR幀的作用是立刻刷新,使錯誤不致傳播,從IDR幀開始,重新算一個新的序列…

gen_caltab生成標定文件

目錄gen_caltab(算子)描述參數gen_caltab(算子) gen_caltab - 為具有矩形排列標記的校準板生成校準板描述文件和相應的PostScript文件。 gen_caltab(:: XNum,YNum,MarkDist,Diamet…

主席樹,喵~

稍微總結一下主席樹吧 Too Difficult!搞了一天搞出一大堆怎么令人悲傷的辣雞代碼。總之先總結一下吧,以后碰到這種問題直接拿去毒害隊友好了。 UPD 5/24 茍狗是沙比 一個節點記錄三個信息:lson,rson,sum 用pid表示節點個數。 build void buil…

【轉】小白級的CocoaPods安裝和使用教程

原文網址:http://www.jianshu.com/p/e2f65848dddc 百度有很多CocoaPods的安裝教程.第一次看的時候,確實有點摸不透的感覺.經過思考,一步一步來實踐,前后花了三十幾分鐘,才順利使用..所以想了想,我還是寫一個小白級的教程吧.細到每一個細節都說明. 讓你不用10分鐘解決…

常見錯誤總結

少打頭文件 少打using namespace std; 命名沖突&#xff0c;全局變量與局部變量命名一致&#xff0c;導致使用的值不是期望值 邊讀邊寫&#xff0c;導致改后讀&#xff0c;覆蓋寫入的值 長整數移位溢出&#xff0c;1<<63是錯誤的&#xff0c;應該寫成1ll<<63 循環變…

x264_sps_init

x264_sps_init此函數為序列量化集的初始化。主要對結構體x264_sps_t中參數的初始化。 void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) { sps->i_id i_id;首先設置序列參數集的ID b_qpprime_y_zero_transform_bypass判斷碼率控制方法是否是恒定質量…

HALCON相機標定相機內參相機外參

目錄相機標定1.相機標定是什么2.怎么使用halcon進行相機內外參標定&#xff1f;&#xff08;1&#xff09;搭建硬件1.**相機連好電腦&#xff0c;用相機廠家軟件打開相機&#xff0c;檢查一下相機是否正常。**2.**接下來使用halcon連接相機**&#xff08;2&#xff09;開始標定…

ionic更改端口號

ionic serve -p 8888 —— 重新指定端口號為8888 serve [options] ............................... 啟動本地服務器進行開發測試 dev/testing   [--consolelogs|-c] ..................... 輸入app的控制臺到ionic的控制臺顯示   [--serverlogs|-s] .....................…

angular change the url , prevent reloading

http://stackoverflow.com/questions/14974271/can-you-change-a-path-without-reloading-the-controller-in-angularjs $location.search({vln: $scope.vln_id}, false);會改變url中 &#xff1f; 后面的 搜索參數&#xff0c;但是controller不會重新實例化。angular 官方文檔…

Ubuntu apt-get 更新/查看軟件

ubuntu 升級軟件&#xff1a; sudo apt-get update 更新源  sudo apt-get upgrade 更新已安裝的包  sudo apt-get dist-upgrade 升級系統 ubuntu升級特定軟件&#xff1a; 可以用 sudo apt-get install pkgname 看軟件安裝位置:dpkg -L xxxx 查看軟件是否安裝&#xff1…

X264設定

--aq-mode <integer> AQ method [1]- 0: Disabled- 1: Variance AQ (complexity mask)說明&#xff1a;自適應量化方法&#xff0c;可以改善某些場景過于模糊等問題&#xff0c;默認開啟- 0: 關閉- 1: 可變AQ推薦值&#xff1a;默認范例&#xff1a;--aq-mode 1--aq-stre…

C#圓形卡尺測量程序基于halcon

廢話不多說上源碼 覺得帖子有用給點個贊哈 先來個效果圖 下邊的是源碼&#xff0c;自己新建一個文件粘貼進去&#xff0c;包含到您現在的項目 中。這串源碼后邊是使用方法。 using System; using System.Collections.Generic; using System.Linq; using System.Text; usin…

MySQL松散索引掃描與緊湊索引掃描

什么是松散索引&#xff1f; 答&#xff1a;實際上就是當MySQL 完全利用索引掃描來實現GROUP BY 的時候&#xff0c;并不需要掃描所有滿足條件的索引鍵即可完成操作得出結果。 要利用到松散索引掃描實現GROUP BY&#xff0c;需要至少滿足以下幾個條件&#xff1a;◆ GROUP BY 條…

算法馬拉松24

算法馬拉松24 A 小C的多邊形 題意&#xff1a;n1個點的多邊形。給外圈的邊標記上1~n&#xff0c;里圈的邊也標記上1~n&#xff0c;使得對于一個外圈相鄰點與中間點構成的三角形的邊權之和都相等。\(n \le 10^6\) 題解&#xff1a;顯然每個三角形權值和為\(\frac{3(n1)}{2}\) 一…