文章目錄
- 1. 數字表示
- 2. static, extern, auto, register, volatiate
- 3 聯合體union
- 4 結構體與位域
1. 數字表示
整數:
浮點數:
2. static, extern, auto, register, volatiate2.1 變數
儲存方式:
靜態儲存
動態儲存裝置
棧stack |
|
堆heap |
|
待用資料區 |
資料區段.data |
|
未初始化資料區段.bss |
程式段 |
.text |
資料區段和未初始化資料區段組成了靜態儲存區
堆、棧組成了動態儲存裝置區
一般情況下,全域變數、static局部變數都位於靜態儲存區
非static的auto變數、函數調用時的現場保護和返回地址位於棧,而動態分配的空間位於堆
一。局部變數
1. auto變數
隱含為自動儲存類別,屬於動態儲存裝置。auto關鍵字可省略
2. static聲明的局部變數,或靜態局部變數
屬於靜態儲存,在函數調用結束後仍然存在
但是注意:雖然靜態局部變數在函數調用結束後仍然存在,但其他函數是不能引用它的
3. register聲明的局部變數
只有局部auto變數和形式參數可以作為寄存器變數。局部靜態變數不能作為register變數
二。外部變數(或全域變數)
1。一個檔案內聲明的外部變數
例:
main()
{
extern A, B;
printf("%d", A);
}
int A=1, B=-8;
2. 在多個檔案中聲明外部變數
作用:擴充外部變數的範圍
//file1.c
int A;
main()
{
//...
}
//file2.c
extern A;
power(int n)
{
//..
}
3. static聲明的外部變數
作用:將外部變數的範圍只限於該檔案引用,而不能被其他檔案引用。
//file1.c
static int A;
main()
{
//...
}
//file2.c
extern A;
fun(int n)
{
A=A*n;
//...
}
//error: file2.c cannot use the A, although declare it as extern
三。變數和聲明的區別:
對於函數:區別很明顯
函數的聲明是函數的原型
函數的定義是包含有函數體,即函數的實現
對於變數:
廣義的聲明,包含定義,分為定義性聲明(defining declaration)和引用性聲明(或非定義性聲明,reference declaration)
狹義的聲明,即指非定義性聲明
定義性聲明指需要建立儲存空間,而引用性聲明不需要建立儲存空間
一般為了敘述方便,把建立儲存空間的聲明稱為定義,而把不需要建立儲存空間的聲明稱為聲明。顯然,這裡的聲明是狹義的,即非定義性聲明
2.2 函數
1. 內建函式
如:
static int fun(int a, int b)
{
//...
}
使用內建函式,可以使函數只局限於所在檔案
2. 外部函數
1) 如:
extern int fun(int a, int b);
這樣,函數fun就可以在其他檔案調用。C語言規定,如果在定義函數時省略extern,則隱含為外部函數。
2) 在需要調用此函數的檔案中,用extern聲明所用的函數是外部函數。此extern也可以省略,而唯寫函數原型
總結:
從範圍角度分,有局部變數和全域變數
- 局部變數
- 自動變數,即動態局部變數(離開函數,值就消失)
- 靜態局部變數(離開函數,值仍保留)
- 寄存器變數(離開函數,值就消失)
- 全域變數
- 靜態外部變數(只限本檔案引用)
- 外部變數(即非靜態外部變數,允許其他檔案引用)
從變數生命期分,有動態儲存裝置和靜態儲存
- 靜態儲存
- 靜態局部變數(函數內有效)
- 靜態外部變數(本檔案內有效)
- 外部變數(其他檔案可引用)
- 動態儲存裝置
3 聯合體union
定義聯合體和聯合體變數
如:
union sa_union
{
int i;
char ch;
float f;
}a, b, c;
但是注意:不能引用聯合體變數,只能引用聯合體變數中的成員,如a.i, b.ch, c.f
printf("%d", a);
//error!!!
1)每個瞬時只能存放其中一種,不能同時起作用
2)聯合體變數中起作用的成員是最後一次存放的成員,存入一個新的成員後原來的成員就失去了作用
3)聯合體變數的地址和它的各成員的地址都是同一地址,例如&a, &a.i, &a.c, &a.f都是同一地址值
4)以下都是錯誤的:
- 引用聯合體變數名得到一個值,但可以使用聯合體變數的指標
- 在定義聯合體變數是對它初始化
- 將聯合體變數作為函數參數
- 使函數返回聯合體變數
4 結構體與位域
C語言中允許在一個結構體中以位為單位來指定其成員所佔記憶體長度,這種以位為單位的成員稱為“位域”
struct packed_data
{
unsigned a:2;
unsigned b:6;
unsigned c:4;
unsigned d:4;
int i;
}data;
a, b, c, d一共佔2位元組,i佔4位元組
sizeof(data)=8
struct packed_data
{
unsigned a:2;
unsigned b:3;
unsigned c:4;
int i;
}data;
1. 一個位域必須儲存在同一個位元組中,不能跨兩個位元組。如一個位元組所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:
struct bs
{
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*從下一單元開始存放*/
unsigned c:4
}
在這個位域定義中,a占第一位元組的4位,後4位填0表示不使用,b從第二位元組開始,佔用4位,c佔用4位。
2. 由於位域不允許跨兩個位元組,因此位域的長度不能大於一個位元組的長度,也就是說不能超過8位二進位。
3. 位域可以無位網域名稱,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:
struct k
{
int a:1
int :2 /*該2位不能使用*/
int b:3
int c:2
};
從以上分析可以看出,位域在本質上就是一種結構類型, 不過其成員是按二進位分配的。