導言:
在C語言中,變量的存放位置有多種,可以存放在棧區,可以存放在全局靜态區等(這些區域都是對記憶體劃分的結果),一般對于變量而言,我們比較關注它的生命周期和作用域:
生命周期:從變量的空間被申請,直至空間被釋放掉的這段時間(所在的{}内,{}結束,該變量被自動釋放)
作用域:所在{}内,出了{},變量就沒用了
一、自動變量(局部變量/棧區變量)
如 int a ,int a[4],int *p ,struct AAA a[3]這些都是局部變量(函數的形參也是局部變量,如void fun(int a,int b){}針對于fun這個函數,a和b變量也是局部變量,隻在所在的{}範圍内起作用),局部變量又稱為自動變量或者棧區變量,它隻在它本身所在的{}範圍内起作用(從聲明變量的位置開始),一出這個範圍,就失效了(生命周期結束),請看如下代碼:
#include <stdio.h>
int main(void)
{
int a;
{
int b;
b = 23;
a = 32;
}
return 0;
}
分析1:變量a的範圍是在最外層的{}内,在最外層的{}内,均可以使用變量a,而b的作用範圍是在内層的{},如果出了内層的{},那麼b就不再生效了。以上的代碼是沒有問題的,與我們所講的理論相符合。再來看如下代碼:
#include <stdio.h>
int main(void)
{
int a;
{
int b;
b = 23;
a = 32;
}
b = 55;
return 0;
}
如果是用以上的代碼,進行編譯的話,那麼會出現如下錯誤:
分析2:因為b的作用範圍是在内層的{}内,如果出了這個範圍,那麼b就已經消失了,不能夠再次使用它了,是以編譯器報了這樣一個錯誤。
注意:
#include <stdio.h>
int main(void)
{
auto int a;
int b;
return 0;
}
分析:我們在編碼中定義變量常常使用int a的形式,其實也可以這樣auto int a,這兩者是完全等價的。
二、靜态變量(此處的靜态變量包含全局變量)
特點:
存儲位置:靜态區/靜态全局區/靜态存儲區
特性:①靜态變量會被自動初始化成0 ②生命周期與程式共存亡 ③在程式運作時(第一步就是要加載資源),在加載資源階段配置設定空間(在執行主函數之前,需要加載程式所需資源,對于局部變量空間的開辟是在程式運作的階段)
1.全局變量/外部變量(外部可以使用,目前檔案可以使用,其它檔案也可以使用)
特點:在{}範圍外,在不手動進行初始化的情況下,編譯器預設為全局變量進行了初始化,如果是int型變量初始化為0,如果是指針,初始化為NULL
注意:全局變量的定義 int a =12 ;與 此條語句等價:extern int a = 12;因為本身全局變量就是外部變量,一般而言extern 加在聲明處,用來說明int a已經定義(讓看代碼的人更明确),一般這是屬于一種共識.
#include <stdio.h>
int a ;
int b[3];
int *p ;
struct Node
{
int a;
double b;
}node ;
int main(void)
{
printf("%d\n",a);
printf("%d,%d,%d\n", b[0],b[1],b[2]);
printf("%p\n", p);
printf("%d,%lf\n", node.a,node.b);
return 0;
}
觀察如下運作結果:
注意:① 在全局變量的位置,隻能寫函數的聲明,變量的聲明或者初始化,并且變量的初始化隻能使用常量進行初始化
② 所有檔案均可見,但是必須先聲明,聲明後才能使用,比如int a =12 ;已經在主檔案中定義,那麼在别的檔案如果想要使用a這個變量的話,必須先使用int a;語句進行聲明,記住,此時僅僅是聲明。
2.靜态全局變量
含義:将全局變量加上一個存儲類說明符static。
生命周期:和程式共存亡。
作用域:隻在所在的檔案内有效
3.靜态局部變量
含義:将局部變量加上一個存儲類說明符static。
作用域:隻在所在的{}内有效(與局部變量作用域一樣)
生命周期:與程式共存亡
例子:
#include <stdio.h>
void fun()
{
int a = 1;
static int b = 1;
a++;
b++;
printf("a:%d,b:%d\n",a,b);
}
int main(void)
{
fun();
fun();
fun();
return 0;
}
結果截圖: