聲明定義雖然無處不在,但是真正的想區分它們,卻不是表面上那麼簡單。
首先,從廣義的角度來講聲明中包含著定義:定義又可以稱之為,“聲明性定義”;而狹義的聲明,有可稱之為“引用性聲明”。
下面,我們就來討論“聲明性定義”與“引用性聲明”。的區別,之後簡稱定義與聲明。
1、定義時系統會為定義的變量分配空間,而聲明時,不會分配空間。這個是本質上的區別。
2、定義在程序中只能出現一次,而聲明可以多次。比如:
如果兩個c中有相同的全局變量“定義”,且沒有初始化,編譯器會認為第二個是聲明而不是定義。
所以連續寫兩個int a;int a; 編譯也不會出錯,但是連續寫int a = 1;int a = 1;編譯出錯。(函數也一樣)
3、由2可見,在定義變量時初始化的副作用是告訴編譯器,這是一個定義,而不是一個聲明。因為聲明時,是不可以
初始化的,具體的例子就是 extern int a; 這表示這是個聲明而不是定義。如果寫成extern int a = 1;編譯就會報錯。
結合1來想,這個就很正常了,因為聲明是沒有分配空間的,如何賦值呢?
4、定義時可以完成聲明,並且初始化!例如 int a = 0; //定義,聲明,初始化就包含這一條語句之中。
//--------關於extern的用法-------------------
extern的作用就是進行聲明,實現調用其他文件的全局變量,或者函數。
由於聲明可以多次,一般有的變量會被其他文件文件調用,那麼一般會在該文件的頭文件多聲明一次改變量——extern + 變量。
那麼如果另外一個文件包含了該頭文件,就可以調用該變量。
//--------關於struct的聲明定義初始化-------------------
1、struct的定義(這裡注意的是,struct定義的是類型,而不是變量;但是以上結論同樣適用!)
struct people //定義類型
{
char name[20];
int age;
};
2、struct people; //聲明類型,同樣寫兩句一模一樣的不會錯!但是類型定義也只能一次。
3、定義類型時,同時利用類型聲明(定義)變量。這裡類肯定是定義好了,而s1如果沒有其他初始化代碼,這裡就是即聲明又定義了。
struct student
{
char name[20];
int age;
}s1;
4、結構體變量的初始化,這個需要在3的前提下,這種形式的初始化可以不按照定義時的順序,可帥氣的稱之為“亂序初始化”
struct student s1 =
{
.age = 10,
.name = "linux", //注意初始化結構體變量是用的是逗號,而定義結構體類型時,用的是分號。
};
5、省略掉類型的聲明(定義)
struct
{
char name[20];
int age;
}s1;
但是無法像4中那樣單獨的初始化。
6、定義結構體類型時,無法初始化結構體變量,如下寫法會報錯:
struct student //錯誤寫法
{
char name[20] = linux ;
int age = 10;
}s1;
7、於似乎再次發現一種神奇的寫法:這樣寫也是有效的
struct student
{
char name[20];
int age;
}s1 =
{
.age = 10,
.name = "linux",
};
8、去掉類型名字,這樣寫也是有效的
struct
{
char name[20];
int age;
}s1 =
{
.age = 10,
.name = "linux",
};
定義結構體類型,同時定義結構體變量,並初始化變量,就是這麼帥~~
9、struct {}a和 struct a{} 的區別
前者是定義了a(結構體)變量,後者是定義了結構體類型a。
//--------關於enum的聲明定義初始化-------------------
這個就直接摘抄朱老師(朱有鵬)筆記吧。
/*
****************************************************************
* enumeration 類型定義
****************************************************************
*/
// 定義方法1,定義類型和定義變量分離開
enum week
{
SUN, // SUN = 0
MON, // MON = 1;
TUE,
WEN,
THU,
FRI,
SAT,
};
enum week today;
// 定義方法2,定義類型的同時定義變量
enum week
{
SUN, // SUN = 0
MON, // MON = 1;
TUE,
WEN,
THU,
FRI,
SAT,
}today,yesterday;
// 定義方法3,定義類型的同時定義變量
enum
{
SUN, // SUN = 0
MON, // MON = 1;
TUE,
WEN,
THU,
FRI,
SAT,
}today,yesterday;
// 定義方法4,用typedef定義枚舉類型別名,並在後面使用別名進行變量定義
typedef enum week
{
SUN, // SUN = 0
MON, // MON = 1;
TUE,
WEN,
THU,
FRI,
SAT,
}week;
// 定義方法5,用typedef定義枚舉類型別名,並在後面使用別名進行變量定義
typedef enum
{
SUN, // SUN = 0
MON, // MON = 1;
TUE,
WEN,
THU,
FRI,
SAT,
}week;
結構體,枚舉,使用方法總結:
1、結構體,枚舉使用有很多相似的地方;
2、定義枚舉類型時,用的是分號。而且可以同時初始化其實的變量。
3、枚舉類型不管是類型名還是,枚舉內部的變量都是全局的,所以都不能重名。而結構體內部的變量是局部的。
4、使用枚舉是可以直接用其中的變量如:SUN;而結構體需要這麼訪問:s1.age
最後是關於static的聲明:
static來聲明一個變量的作用有二個:
(1)對於局部變量用static聲明,則是為該變量擁有全局變量的特性——在整個程序的執行期內都始終存在。因為他和全局變量一樣在數據段。而不再棧上。
同時擁有局部變量的特性——無法被外部程序訪問,這個就是生命周期的問題。
(2)全局變量或者是函數用static來聲明,則起到“隱蔽”的作用——該變量的作用域只限於本文件。其他文件無法訪問。
加上extern也不行。