本篇博文主要是记录一下自己肤浅的理解,同时帮助跟我一样正在学习过程中的同伴。请大佬们指出文中不妥之处,万分感谢!

  相信学习C/C++语言的小白对extern并不陌生,根据自己的学习,和大家交流一下extern的相关知识

1 extern概念

  extern是C/C++中的一个关键字,主要是针对变量和函数而言。

  这里只讨论变量。

2 extern作用

   extern用于声明外部变量。提到这里,就不得不说一下声明和定义两个概念。

2.1 变量声明

  声明:用于向程序表明变量的类型和名字。声明不分配内存空间。

2.2 变量定义

  定义:给变量分配内存空间,还可以给变量赋初始值。

变量可以有多次声明,但是有且只能有一次定义

定义也是声明,但是extern声明不是定义,也不分配内存空间,除非给extern变量赋初值时才是定义

2.3 声明和定义举例

(1)未初始化

  1. int i; //声明,也是定义,只不过没有初始化
  2. extern int i; //声明,不是定义

(2)初始化

  1. 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中要使用

  1. /*a.c*/
  2. #include<stdio.h>
  3. int age;
  4. int main()
  5. {
  6. age = 18;
  7. printf("I am %d years old", age);
  8. return 0;
  9. }
  1. /*b.c*/
  2. #include<stdio.h>
  3. extern int age; //声明为外部变量
  4. int main()
  5. {
  6. age = 19;
  7. printf("I am %d years old", age);
  8. return 0;
  9. }

4.2 自定义类型定义变量

  若是自定义变量,比如结构体,结构体一般是在头文件中定义,那么两个源文件都要包含这个头文件。例如:

  1. /*a.h*/
  2. #pragma once
  3. typedef struct _student
  4. {
  5. char name[20];
  6. int age;
  7. }student;
  1. /*a.c*/
  2. #include<stdio.h>
  3. #include"a.h" //要包含头文件
  4. student stu;
  5. int main()
  6. {
  7. stu->age = 18;
  8. printf("I am %d years old", stu->age);
  9. return 0;
  10. }
  1. /*b.c*/
  2. #include<stdio.h>
  3. #include"a.h" //也要包含头文件
  4. extern student stu;
  5. int main()
  6. {
  7. stu->age = 19;
  8. printf("I am %d years old", stu->age);
  9. return 0;
  10. }

5 static

  static用于定义静态变量。既可以修饰全局变量,又可以修饰局部变量;既可以用于面向过程程序设计,也可以用于面向对象程序设计。面向过程和面向对象使用static关键字有不同。

  static修饰的静态变量,不管是全局静态变量还是局部静态变量,都是放在全局数据区

5.1 面向对象的static

5.1.1 局部静态变量

  static修饰局部变量:该局部静态变量的生命周期在整个程序运行期间都有效,所有的文件都可以访问。

例如:

  1. //example
  2. #include<stdio.h>
  3. int func(int a)
  4. {
  5. static int c = 2;
  6. c += a;
  7. return c;
  8. }
  9. int main()
  10. {
  11. int a = 1, b;
  12. b = func(a++);
  13. printf("b:%d", b);
  14. b = func(a++);
  15. printf("b:%d", b);
  16. return 0;
  17. }

  在函数体内定义变量,变量的作用域仅限于该函数体的一次执行,因为当程序运行到该语句时在在上分配内存,函数该函数体运行完后,该变量的内存会被自动释放。这样,如果我们第二次使用改变量要在第一次使用的基础上时,就出现了问题。

  static关键字正好解决了这一问题,上面也提到过,static关键字修饰的变量存储在全局数据区,可以一直在原来的技术上使用该局部静态变量。

  1. 局部静态变量有以下特点:
  2. 1 局部静态变量在全局数据区分配内存;
  3. 2 局部静态变量在程序执行到该变量的声明处时被首次初始化,以后使用不再初始化;
  4. 3 局部静态变量一般在声明处被初始化,如果没有显式初始化,会被默认初始化为0
  5. 4 它始终在全局数据区,直到程序运行结束。但其作用域仍为局部作用域,当其所在函数或语句块结束时,其随之结束。

5.1.2 全局静态变量

  static修饰全局变量:该全局静态变量作用域只限于本文件,其他文件不能访问。也即在其他文件中定义一个相同名字的变量,编译器不会报错。

例如:

  1. /*file1*/
  2. #include<stdio.h>
  3. static int age; //声明为外部变量
  4. int main()
  5. {
  6. age = 19;
  7. printf("I am %d years old", age);
  8. return 0;
  9. }
  10. /*file2*/
  11. #include<stdio.h>
  12. extern int age; //声明为外部变量
  13. int main()
  14. {
  15. age = 19;
  16. printf("I am %d years old", age);
  17. return 0;
  18. }

  这两个文件编译都没问题,但是运行的时候就会出现错误。将file1中的static int age; 改为int age;之后,两个文件都可编译运行了。

  所以,静态全局变量不能被其他文件引用

参考C语言中声明和定义详解, extern使用方法总结

C/C++中extern和static的更多相关文章

  1. 小胖说事28------iOS中extern,static和const差别和使用方法

    通俗的讲: extern字段使用的时候,声明的变量为全局变量,都能够调用,也有这样一种比較狭义的说法:extern能够扩展一个类中的变量到还有一个类中: static声明的变量是静态变量,变量值改变过 ...

  2. C语言关键字register、extern、static、一些总结,及项目中使用的心得

    首先介绍两个概念: 一.变量的生存周期: 变量从建立到撤销的时间段成变量的生存周期.静态变量,从变量产生到整个程序执行结束.当函数使用变量结束后,变量的存储空间依然存在,变量的值也会随着函数的对其的使 ...

  3. C++中extern “C”含义及extern、static关键字浅析

    https://blog.csdn.net/bzhxuexi/article/details/31782445 1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C ...

  4. 链接(extern、static关键词\头文件\静态库\共享库)

    原文链接:http://www.orlion.ga/781/ 一. 多目标文件的链接 假设有两个文件:stack.c: /* stack.c */ char stack[512]; int top = ...

  5. 【转载】C/C++中extern关键字详解

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  6. C/C++中extern关键字解析

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  7. C/C++中extern关键字详解

    转自:http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777431.html 1 基本解释:extern可以置于变量或者函数前,以标示变 ...

  8. IOS的变量前加extern和static字段

    IOS的变量前加extern和static字段 前一阵子,做项目的时候到网上找Demo,打开运行的时候发现其中变量前有关键字extern和static,所以我研究了一下子 对于extern来说可以理解 ...

  9. C++中extern “C”含义深层探索

    C++中extern “C”含义深层探索 extern “C” 是一个双向都需要用到的语法表示,就是说在cpp引用c头文件,或者c引用cpp文件时都需要用到.但extern “C” 永远只能在cpp引 ...

随机推荐

  1. Python定时任务框架APScheduler

    http://blog.csdn.net/chosen0ne/article/details/7842421 APScheduler是基于Quartz的一个Python定时任务框架,实现了Quartz ...

  2. CSDN Android客户端的制作 导航帖

    弄个导航贴,把相关知识来个汇总. CSDN Android的客户端的效果图: 分别通过以下博客进行详细的讲解: 1.Android 使用Fragment,ViewPagerIndicator 制作cs ...

  3. 树莓派.安装Firefox浏览器

    sudo apt-get install firefox-esr 要做全屏效果的话, 可以加装插件FF Fullscreen 插件地址: https://addons.mozilla.org/en-U ...

  4. channel.go

    )         c.RLock()         client, ok := c.clients[msg.clientID]         c.RUnlock()         if ok ...

  5. 【gcd+stl】UVa1642 Magical GCD

    Description 一个长度为n的数列,选一个连续子序列,使得子序列的公约数*长度最大,求这个最大值.n<=1e5. Solution 连续子序列一般都要用滑动窗口是吧(固定r,快速计算最优 ...

  6. 【最小生成树】Bzoj1601[Usaco2008 Oct]灌水

    Description Farmer John已经决定把水灌到他的n(1<=n<=300)块农田,农田被数字1到n标记.把一块土地进行灌水有两种方法,从其他农田饮水,或者这块土地建造水库. ...

  7. [Noi2015]软件包管理器 BZOJ4196

    分析:水题 每次安装的时候和根节点求lca的过程中区间覆盖+区间查询 每次删除的时候查询子树中安装的数量+区间覆盖 附上代码: #include <cstdio> #include < ...

  8. const和static readonly的区别

    我们都知道,const和static readonly的确很像:通过类名而不是对象名进行访问,在程序中只读等等. 在多数情况下可以混用.二者本质的区别在于,const的值是在编译期间确定的,因此只能在 ...

  9. Hibernate-ORM:02.Hibernate增删改入门案例

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本笔者使用的是Idea+mysql+maven做Hibernate的博客,本篇及其以后都是如此! 首先写好思路 ...

  10. Treap与fhq_Treap学习笔记

    1.普通Treap 通过左右旋来维护堆的性质 左右旋是不改变中序遍历的 #include<algorithm> #include<iostream> #include<c ...