一、全局變數 1. 定義在函數外面的變數是全局變數 2. 全局變數具有全局的生存期和作用域 3. 它們與任何函數無關,在任何函數內部都可以使用它們 二、全局變數初始化 1. 沒有做初始化的全局變數會得到0值 2. 指針會得到NULL值 3. 只能用編譯時刻已知的值來初始化全局變數 4. 它們的初始化 ...
一、全局變數
- 定義在函數外面的變數是全局變數
- 全局變數具有全局的生存期和作用域
- 它們與任何函數無關,在任何函數內部都可以使用它們
#include <stdio.h>
int f(void);
// 全局變數
int gALL = 12;
int main(int argc, char const *argv[])
{
printf("in %s gALL=%d\n", __func__,gALL);
f();
printf("agn in %s gALL=%d\n", __func__,gALL);
return 0;
}
int f(void)
{
printf("in %s gALL=%d\n", __func__,gALL);
gALL += 8;
printf("agn in %s gALL=%d\n", __func__,gALL);
return gALL;
}
// in main gALL=12
// in f gALL=12
// agn in f gALL=20
// agn in main gALL=20
二、全局變數初始化
- 沒有做初始化的全局變數會得到0值
- 指針會得到NULL值
- 只能用編譯時刻已知的值來初始化全局變數
- 它們的初始化發生在main函數之前
三、被隱藏的全局變數
如果函數內部存在與全局變數同名的變數,則全局變數被隱藏
#include <stdio.h>
int f(void);
// 全局變數
int gALL = 12;
int main(int argc, char const *argv[])
{
printf("in %s gALL=%d\n", __func__,gALL);
f();
printf("agn in %s gALL=%d\n", __func__,gALL);
return 0;
}
int f(void)
{
// 這裡定義一個名字相同的變數,那麼全局的就被隱藏了
int gALL = 1;
printf("in %s gALL=%d\n", __func__,gALL);
gALL += 8;
printf("agn in %s gALL=%d\n", __func__,gALL);
return gALL;
}
// in main gALL=12
// in f gALL=1
// agn in f gALL=9
// agn in main gALL=12
四、靜態本地變數
- 在本地變數定義時加上static修飾符就成為靜態本地變數
- 當函數離開的時候,靜態本地變數會繼續存在並保持其值
- 靜態本地變數的初始化只會在第一次進入這個函數時做,以後進入函數時會保持上次離開的值
#include <stdio.h>
int f(void);
int main(int argc, char const *argv[])
{
f();
f();
return 0;
}
int f(void)
{
static int all = 1;
printf("in %s all=%d\n", __func__,all);
all += 9;
printf("agn in %s all=%d\n", __func__,all);
return all;
}
// in f all=1
// agn in f all=10
// in f all=10
// agn in f all=19
註意事項
- 靜態本地變數實際上是特殊的全局變數
- 它們位於相同的記憶體區域
- 靜態本地變數具有全局的生存期,函數內的局部作用域
- static在這裡的意思就是局部作用域(本地可以訪問)
五、後記:返回指針的函數
- 返回本地變數的地址是危險的
- 返回全局變數或靜態本地變數的地址是安全的
- 返回在函數內malloc的記憶體是安全的,但是容易造成問題
- 最好的做法是返回傳入的指針
下麵的寫法就是很危險的
#include <stdio.h>
int* f(void);
void g(void);
int main(int argc, char const *argv[])
{
int *p = f();
printf("*p = %d\n", *p);
g();
printf("*p = %d\n", *p);
return 0;
}
int* f(void)
{
int i = 12;
// 返回本地變數的地址是危險的
return &i;
}
void g(void)
{
int k = 24;
printf("k = %d\n", k);
}
// *p = 12
// k = 24
// *p = 24
tips
- 不要使用全局變數來在函數間傳遞參數和結果
- 儘量避免使用全局變數
- 使用全局變數和靜態本地變數的函數是線程不安全的