• 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使用方法总结

  • 相关阅读:
    快乐
    好好思考
    中秋
    要把收拾房间养成一个习惯_611
    退出微博, 不要再寻求心里安慰。
    Proj CMI Paper Reading: Mining Input Grammars from Dynamic Taints
    Proj CMI Paper Reading: Locating Faults with Program Slicing: An Empirical Analysis
    Proj CMI Paper Reading: Mining Android Apps for Anomalies
    git操作(工作中实际开发流程)
    linux c 常用代码
  • 原文地址:https://www.cnblogs.com/MisterXu/p/10773831.html
Copyright © 2020-2023  润新知