一、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. select监听udp消息

    服务端 #!/usr/bin/python2.6 # -*- coding:utf-8 -*- import json import socket import select def socketse ...

  2. jquery 禁止滚动条滚动,并且滚动条不消失,页面大小不闪动

    一,禁止滚动,滚动条不消失,页面大小不闪动 //禁止滚动条滚动 function unScroll() { var top = $(document).scrollTop(); $(document) ...

  3. React 体验

    https://github.com/facebook/create-react-app npm i -g create-react-app cd  <your-folder> creat ...

  4. 深度优先遍历(DFS)(转)

    优先搜索(DFS, Depth First Search)是一个针对图和树的遍历算法.早在19世纪就被用于解决迷宫问题. 对于下面的树而言,DFS方法首先从根节点1开始,其搜索节点顺序是1,2,3,4 ...

  5. html5 缓存实例

    html5 有两种缓存 1.localStorage:浏览器关闭后,数据库还存在. 2.sessionStorage:session缓存,浏览器关闭后,数据已经不存在. 实例一:localStorag ...

  6. Docker 添加环境系统文件配置

    在 docker 启动文件添加默认环境系统配置 " /etc/default/docker ": 添加  Environment File 配置: # vi /usr/lib/sy ...

  7. C++ 函数的重载和参数默认值

    函数的重载和参数默认值视频教程 函数的重载注意事项: 只会根据三项内容进行重载:参数的个数.参数的类型.参数的顺序 参数默认值: 参数的默认值可以在函数的定义中也可以在函数的声明中,但不能同时有 从第 ...

  8. Python 8 - Socket编程进阶

    本节内容:    1.Socket语法及相关    2.SocketServer实现多并发 Socket语法及相关 socket 概念 socket本质上就是在2台网络互通的电脑之间架设一个通道,两台 ...

  9. mongodb 案例 ~ 经典故障案例

    一 简介:此文汇总遇到过和搜集过的故障案例 二 场景案例 1 问题描述: mongo集群在无任何业务情况下,mongos所在服务器cpu突然被打满,内核日志报错 mongos被hung住,非常奇怪的问 ...

  10. python小练习---TCP客户端

    这是python黑帽子上的起始练习,我对其中的用到的函数做了注释,以便日后便于理解. 该程序可以访问百度,返回响应信息. 另外,我注释还有一部分UDP客户端的语句,TCP和UDP对比便于记忆. # - ...