本篇博文主要是記錄一下自己膚淺的理解,同時幫助跟我一樣正在學習過程中的同伴。請大佬們指出文中不妥之處,萬分感謝!
相信學習C/C++語言的小白對extern
並不陌生,根據自己的學習,和大家交流一下extern
的相關知識
1 extern概念
extern
是C/C++中的一個關鍵字,主要是針對變量和函數而言。
這里只討論變量。
2 extern作用
extern
用於聲明外部變量。提到這里,就不得不說一下聲明和定義兩個概念。
2.1 變量聲明
聲明:用於向程序表明變量的類型和名字。聲明不分配內存空間。
2.2 變量定義
定義:給變量分配內存空間,還可以給變量賦初始值。
變量可以有多次聲明,但是有且只能有一次定義
定義也是聲明,但是extern
聲明不是定義,也不分配內存空間,除非給extern
變量賦初值時才是定義
2.3 聲明和定義舉例
(1)未初始化
int i; //聲明,也是定義,只不過沒有初始化
extern int i; //聲明,不是定義
(2)初始化
extern int i = 666; //有初始化,定義
3 為什么使用extern
比如說有a.c, b.c兩個源文件和一個c.h頭文件,當一個變量在a.c, b.c多個源文件中同時使用時,如果把變量在頭文件c.h中定義,每個*.c文件都包含c.h這個頭文件,這樣編譯器會提示變量多次定義的錯誤。
怎么來避免這個錯誤呢,就該extern
出場了。在一個源文件里定義這個變量,其他源文件使用這個變量時用extern
聲明這個變量為外部變量。
4 怎么使用extern
4.1 基本數據類型定義變量
用基本數據類型定義變量時,只需在一個源文件里定義這個變量,其他源文件使用這個變量時用extern
聲明這個變量為外部變量。例如:
在a.c中定義的變量b.c中要使用
/*a.c*/
#include<stdio.h>
int age;
int main()
{
age = 18;
printf("I am %d years old", age);
return 0;
}
/*b.c*/
#include<stdio.h>
extern int age; //聲明為外部變量
int main()
{
age = 19;
printf("I am %d years old", age);
return 0;
}
4.2 自定義類型定義變量
若是自定義變量,比如結構體,結構體一般是在頭文件中定義,那么兩個源文件都要包含這個頭文件。例如:
/*a.h*/
#pragma once
typedef struct _student
{
char name[20];
int age;
}student;
/*a.c*/
#include<stdio.h>
#include"a.h" //要包含頭文件
student stu;
int main()
{
stu->age = 18;
printf("I am %d years old", stu->age);
return 0;
}
/*b.c*/
#include<stdio.h>
#include"a.h" //也要包含頭文件
extern student stu;
int main()
{
stu->age = 19;
printf("I am %d years old", stu->age);
return 0;
}
5 static
static
用於定義靜態變量。既可以修飾全局變量,又可以修飾局部變量;既可以用於面向過程程序設計,也可以用於面向對象程序設計。面向過程和面向對象使用static
關鍵字有不同。
static
修飾的靜態變量,不管是全局靜態變量還是局部靜態變量,都是放在全局數據區。
5.1 面向對象的static
5.1.1 局部靜態變量
static
修飾局部變量:該局部靜態變量的生命周期在整個程序運行期間都有效,所有的文件都可以訪問。
例如:
//example
#include<stdio.h>
int func(int a)
{
static int c = 2;
c += a;
return c;
}
int main()
{
int a = 1, b;
b = func(a++);
printf("b:%d", b);
b = func(a++);
printf("b:%d", b);
return 0;
}
在函數體內定義變量,變量的作用域僅限於該函數體的一次執行,因為當程序運行到該語句時在在棧上分配內存,函數該函數體運行完后,該變量的內存會被自動釋放。這樣,如果我們第二次使用改變量要在第一次使用的基礎上時,就出現了問題。
static
關鍵字正好解決了這一問題,上面也提到過,static
關鍵字修飾的變量存儲在全局數據區,可以一直在原來的技術上使用該局部靜態變量。
局部靜態變量有以下特點:
1 局部靜態變量在全局數據區分配內存;
2 局部靜態變量在程序執行到該變量的聲明處時被首次初始化,以后使用不再初始化;
3 局部靜態變量一般在聲明處被初始化,如果沒有顯式初始化,會被默認初始化為0;
4 它始終在全局數據區,直到程序運行結束。但其作用域仍為局部作用域,當其所在函數或語句塊結束時,其隨之結束。
5.1.2 全局靜態變量
static
修飾全局變量:該全局靜態變量作用域只限於本文件,其他文件不能訪問。也即在其他文件中定義一個相同名字的變量,編譯器不會報錯。
例如:
/*file1*/
#include<stdio.h>
static int age; //聲明為外部變量
int main()
{
age = 19;
printf("I am %d years old", age);
return 0;
}
/*file2*/
#include<stdio.h>
extern int age; //聲明為外部變量
int main()
{
age = 19;
printf("I am %d years old", age);
return 0;
}
這兩個文件編譯都沒問題,但是運行的時候就會出現錯誤。將file1中的static int age;
改為int age;
之后,兩個文件都可編譯運行了。
所以,靜態全局變量不能被其他文件引用。