宣告&定義 ( Declarations & Definitions )
將[宣告]與[定義]的細微不同分辨清楚,不混淆
https://en.wikipedia.org/wiki/Declaration_(computer_programming)
語法;寫法:
全局變數 |
函式
|
|
宣告 | extern int i; |
void function( void );
或 extern void function( void );
|
定義 | int i; | void function( void ) { ...內容... } |
編譯器行為 compiler behavior:
宣告變數 | 只告知 compiler 變數的存在,和告知變數的型態。 |
定義變數 | 叫 compiler 為變數分配儲存空間。 (當然也得知變數的存在與型態) |
若程式只有一個檔案
金句:當程式只有一個檔案,變數就用定義就夠了。
不需要使用到變數宣告。
變數與函式,使用前必須先定義,而且也只能定義這唯一的一次。
(分配儲存空間當然只能唯一的一次)
正確
// file.c int main( void ) { int var = 1; // 定義,並且設定初始值 var++; // 將var變數值+1 return 0; } |
錯誤:未定義
// file.c int main( void ) { var++; // compiler 未分配 var 空間 return 0; } |
錯誤:重複定義
// file.c int main( void ) { int var = 1; // 定義 var++; return 0; } |
若程式有多個檔案
當程式是多個檔案,才有使用宣告的必要。
現代習慣做法,原則為:
『把宣告寫在.h檔,把定義寫在.c檔』
若沒按照這個原則,在.h檔裡放了定義,
當某.h檔有多個.c檔去 include它,就會產生重複定義的錯誤。
可以宣告很多次,但定義必須是唯一的!
(記得宣告只是得知變數的存在與型態,所以可以宣告很多次)
(定義還會分配儲存空間,當然只能唯一的一次)
多檔案(multiple files)下的宣告,編譯器會自動從所有檔案中尋找它的定義。
var.h
// var.h extern int globalVar; // 變數宣告 void function( void ); // 函式宣告 |
var.c
// var.c #include "var.h" #include <stdio.h> int globalVar = 1; // 變數定義,並且設定初始值 void function( void ) // 函式定義 { printf("Variable is : %d\n", globalVar); } |
file.c
// file.c #include "var.h" // 只要 include .h檔的宣告, // 即可使用定義在其他檔案的全局變數 int main( void ) { globalVar++; function(); return 0; } |
請在定義變數時,設定初始值!
定義變數,沒有設定初始值,其值是無法保證的。
#include <stdio.h> int main( void ) { int sum; // 沒有設定初始值 for( int i = 0 ; i < 5 ; i++ ) sum++; // 無法保證數值是什麼 function( ); return 0; } |
註:全局變數初始值
不要在宣告變數時,設定初始值!
※在宣告變數的同時設定初始值,會轉變成定義。
例如:extern int i=1; 是定義,不要這樣寫,容易混淆視聽..
請拆開來..
.h
extern int i; //宣告 i,寫在.h檔 |
.c
int i = 1; //定義 i,此時設定初始值,寫在.c檔
全局變數&局部變數
全局變數(Global Variable):定義在函式之外的變數。
局部變數(Local Variable):定義在大括號 { } 之內的變數。
int global_var; //全局變數:生命週期直到程式結束,而且跨檔案共享
int main( void )
{
int block_var; //局部變數:生命週期在大括號 { } 之間
return 0;
}
static
static 變數 & static 函式
static:是〝私有化〞的概念
static 表示其:
1.存取的範圍:只在定義的文件檔內,不具跨文件檔共享。
2.生命週期:直到程式結束,才會從記憶體消逝。
現在習慣應用在,模組化的程式!
把大的程式,拆解為功能獨立的小程式,各自寫在不同的.c檔內。
將只有在模組用到的變數&函式設為 static,讓這些 static 只在模組內的.c檔使用。
定義 static 的寫法:
static通常寫在.c檔
static int i;
static void function( void ) { ..........內容.......... }
思考:
若想要宣告static在.h檔,則所有include了.h的.c檔都會產生static,
必須思考目的為何?是否為想要的效果,be careful。
變數的儲存週期 https://www.ptt.cc/bbs/b97902HW/M.1226692638.A.F2B.html |
struct;結構
struct 結構的[宣告]與[定義]
struct S; // declares S
struct S { int a; int b; }; // defines S, S::a, and S::b
私用的 private struct
// s.c #include <stdio.h> struct justInFile { // 結構定義 int integer; float f; }; struct justInFile entity; // 這裡才做出實體entity,分配空間 void function( void ) { printf("i=%d\n", entity.integer); return; } |
不跨檔案使用的、私用的 struct definition 應該寫在 .c 檔,這很正常
但是跨檔案使用的、公開的 struct definition 建議寫在 .h 檔。why?
思路寫在另一篇
http://ashinzzz.blogspot.tw/2012/12/struct-declaration.html
。
int a;只能定義一次?
int a;暫時定義?
重複寫定義,到底? 暫時定義是不會配置記憶體空間的???
參考
神人http://hsian-studio.blogspot.tw/2008/09/blog-post_126.html
神整理http://www.ptt.cc/bbs/C_and_CPP/M.1315949529.A.DD0.html
錯誤http://libai.math.ncu.edu.tw/bcc16/C/C/b-9.shtml
5 則留言:
Nice!!!
請問最後結構 為什麼跨檔公開要把定義寫在.h?
你好,我google後得到的結論是:
若把結構定義寫在.c檔,每個.c檔都要寫一次定義,
當你要做修改,就要一個一個改,很不方便,修改有出錯的風險。
詳細的思路&範例我近期再整理一篇文章好了。
您好,我利用dev C 這套IDE來練習您的跨檔案變數
我開了三個原始碼,分別存了 var.c var.h file.c
檔名和您取的一樣
我將var.h存檔
然後各別編譯 var.c和file.c
file.c編譯時 提示
未定義的 globalVar
未定義的 function
請問我是漏了什麼步驟嗎?
猜可能是dev不能處理"中文空格"的關係?
我為了網頁排版 程式縮排,前面都有一些"肉眼看不到的全形的中文空格"
-------------------------------------------------
// 即可使用定義在其他檔案的全局變數
globalVar++;
-------------------------------------------------
把前面的空格都刪掉,像以下:
-------------------------------------------------
// 即可使用定義在其他檔案的全局變數
globalVar++;
-------------------------------------------------
可能就可以編譯過了?
張貼留言