一、extern

概述

编译器是由上至下编译源文件的,当遇到一些函数引用外部全局变量,而这个变量被定义在该函数声明主体的下方,又或者引用自其它的编译单元,这个情况就需要extern来向编译器表明此变量是一个外部变量

问题1.运用extern实现全局变量声明提升效果

#include <stdio.h>

void fun(void);

int main(void)
{
fun();
} void fun(void)
{
printf("%d\n", v);
} int v = ;

上述代码,全局变量v被声明在函数fun主体的下方,这时编译器将无法找到变量v,报告错误

error: ‘v’ undeclared (first use in this function)

这种情况下可以把变量v的声明提升到函数fun之前

int v = ;
void fun(void)
{
printf("%d\n", v);
}

又或者在函数内部用extern关键字向编译器表明,这是一个来自外部的变量

void fun(void)
{
extern int v;
printf("%d\n", v);
}

extern声明的变量是不能赋值的(但是函数可以),编译器将会自动在外部寻找全局变量v进行赋值

问题2.引用编译单元以外的变量

有一个文件a.c,main函数包含了来自文件b.c的全局变量v

#include <stdio.h>

int main(void)
{
extern int v;
printf("%d\n", v);
}

文件b.c

int v = ;

如果a文件不声明extern int v,编译器将无法通过编译,而声明了extern int v,可以通过编译器仅编译不链接选项,把a.c和b.c先编译,再进行链接,程序便可以顺利运行

gcc -c a.c b.c
gcc -o out a.o b.o

函数和其他类型的变量,数据类型也是可行的哦

#include <stdio.h>

extern void fun(void);
int main(void)
{
fun();
}

定义在一个外部文件b.c的函数fun

#include <stdio.h>

void fun(void);
void fun(void)
{
printf("fun\n");
}

PS:上面提到过extern声明的变量是不能赋值的,但是函数可以。b.c可以改写为

#include <stdio.h>

extern void fun(void);
extern void fun(void)
{
printf("fun\n");
}

表明它是一个外部函数,其实extern是函数存储类修饰符的一个默认类型(extern、static、auto、restrict),所以就算省略掉extern,代码还是可以运行的,请参考c语言核心技术的第11章

二、static

概述

在对extern的描述中得知extern是函数存储类修饰符的一个默认类型,所以就算函数声明中不表明为extern,外部文件也是可以访问该函数的,如果有一种情况希望外部文件不能访问内部文件声明的函数,这时static关键字就派上了用场

让我们修改一下之前的例子

文件a.c

#include <stdio.h>

extern void fun(void);
int main(void)
{
fun();
}

文件b.c

#include <stdio.h>

static void fun(void);
static void fun(void)
{
printf("fun\n");
}

此时fun函数被声明为static,只有内部文件才能够对其进行调用,外部文件a.c若企图调用,在创建链接阶段编译器便会抛出错误提示

undefined reference to `fun'

[C]控制外部变量访问权限的extern和static关键字的更多相关文章

  1. iOS重写和成员变量访问权限

    一.重写机制 1.覆盖父类的方法 2.对父类方法做进一步的补充 注意:父类声明过得方法,子类无需声明. * 子类如果重写了父类的方法: 1.父类的指针指向子类的对象,则调用方法时,调用的是子类的方法: ...

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

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

  3. Struts2 利用拦截器 interceptor 控制登陆和访问权限

    最近学习了Struts2的登录和权限控制用到的是拦截器,需要在struts.xml中配置,每个action都默认的继承defaultStack,如果你用了别的拦截器,还需要手动引入defaultSta ...

  4. 关于private,default,protected,public,成员变量访问权限

    关于private,protected,public,default成员变量的访问权限,请参阅上图! 子类要访问父类的private成员变量,必须采用采用get方法: eg: public class ...

  5. Python变量访问权限控制

    oop1.py文件代码 # user/bin/python class Foo: def bar(self): print('ok') def hello(self, name): print(&qu ...

  6. DACL原理.控制文件的访问权限(文件,注册表.目录.等任何带有安全属性的对象.)

    目录 一丶简介 1.DACL是什么. 2.如何创建一个自己控制的文件. 3.SDDL是个什么鬼. 二丶 编写SDDL 控制的文件 一丶简介 1.DACL是什么. DACL称为自主访问的控制列表.是应用 ...

  7. MVC 5 中Filter控制 action的访问权限

    1,创建一个继承自 FilterAttribute, IActionFilter的类 namespace HeatMetering2.Filters { public class HMV2Authen ...

  8. vue路由权限之访问权限(meta控制是否有访问权限)

    首先登录那权限表 router.beforeEach((to, from, next) => { if(to.path === '/login') { next(); }else{ if(!st ...

  9. 关于extern和static关键字引出的一些关于作用域和链接属性和存储类型的问题

    在进入正题前我们必须了解一些概念: 标识符:标识符不仅仅代表着变量的名字,main()函数的main也是一个标识符,这点很重要. 存储类型:即变量的存储位置及其生存周期:静态区:分为两块 .date ...

随机推荐

  1. Windows Server 2008 R2中无法使用360免费Wifi的解决方案

    为了使主机和虚拟机在同一个无线网络中,而虚拟机的系统是Windows Server 2008 R2 64位的,使用360免费wifi,始终无法开启.在网上查找解决方案,终于找到了原因:Windows ...

  2. RNN

    在DNN中,当前输出层的值只和当前输入值有关系.如果当前输出值不仅依赖当前输入值,也依赖于前面时刻的输入值,那么DNN就不适用了.因此也就有了RNN. 一.RNN结构 这是最简单的RNN.其中Xt是t ...

  3. orcle查看表空间数据文件使用情况

    -- 查看表空间数据文件使用情况select a.*, round(a.usedgb/a.maxgb*100) || '%' usedPer from (select t.TABLESPACE_NAM ...

  4. Java SE之正则表达式一:概述

    正则表达式 概念 定义:符合一定规则的表达式 作用:用于专门操作字符串 特点:用于一些特定的符号表示代码的操作,这样就简化了长篇的程序代码 好处:可以简化对字符串的复杂操作 弊端:符号定义越多,正则越 ...

  5. lua 的语法糖

    tb = {} function tb:fun1() self ---tb end function tb.fun2() self ---->无 end tb:fun1() tb.fun2() ...

  6. luogu P3235 [HNOI2014]江南乐

    传送门 这题又是我什么时候做的(挠头) 首先是个和SG函数有关的博弈论,SG=0则先手必败.显然一堆石子就是一个游戏,而若干堆石子的SG值就是每堆SG的异或和,所以算出每堆石子SG就能知道答案 然后怎 ...

  7. 使用flask_socketio实现客户端间即时通信

    前期没有来得及好好总结,现在复习总结一下: Socket.IO 背后主要的思想是你可以发送和接收想要的任何事件,携带你想要的任何数据.任何可以编码为 JSON 的对象都可以做到,并且也支持二进制数据. ...

  8. Miller-Rabin判质数和Pollared-Rho因数分解

    朴素判质数:$ 在[2..\sqrt{n}]$范围内枚举逐一判断是不是$ n$的因数 时间复杂度:$ O(\sqrt{n})$ 当n达到$ 10^{18}$级别时,显然效率过低 Miller-Rabi ...

  9. window 安装gcc交叉编译器

    参考网址:  https://blog.csdn.net/zsy19881226/article/details/46952535

  10. 一张图片资源要占用多大内存xhdpi xxhdpi

    一张图片资源要占用多大内存,可以用下面的计算公式计算 4 * withPixel*(targetDensity /sourcedensity) * heightPixel*(targetDensity ...