C/C++中extern和static


  本篇博文主要是記錄一下自己膚淺的理解,同時幫助跟我一樣正在學習過程中的同伴。請大佬們指出文中不妥之處,萬分感謝!
  相信學習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;之后,兩個文件都可編譯運行了。
  所以,靜態全局變量不能被其他文件引用

參考C語言中聲明和定義詳解, extern使用方法總結


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM