zoukankan      html  css  js  c++  java
  • [C]控制外部变量访问权限的extern和static关键字

    一、extern

    概述

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

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

    #include <stdio.h>
    
    void fun(void);
    
    int main(void)
    {
        fun();
    }
    
    void fun(void)
    {
        printf("%d
    ", v);
    }
    
    int v = 5;

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

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

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

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

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

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

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

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

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

    #include <stdio.h>
    
    int main(void)
    {
        extern int v;
        printf("%d
    ", v);
    }

    文件b.c

    int v = 12;

    如果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
    ");
    }

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

    #include <stdio.h>
    
    extern void fun(void);
    extern void fun(void)
    {
        printf("fun
    ");
    }

    表明它是一个外部函数,其实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
    ");
    }

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

    undefined reference to `fun'
  • 相关阅读:
    Visual C# 2008+SQL Server 2005 数据库与网络开发14.1.2 WPF的组成
    Visual C# 2008+SQL Server 2005 数据库与网络开发13.1.3 简单记事本程序菜单设计
    Visual C# 2008+SQL Server 2005 数据库与网络开发13.1.1 菜单创建
    Feathers TextInput使KeyboardEvent失效
    UILabel 多行显示
    突破flash player的睡眠模式
    突破flash player睡眠模式 后续
    缩放UIImage
    IT菜鸟报到!
    用VMware装了Ubuntu后,安装VMware Tools
  • 原文地址:https://www.cnblogs.com/yiyide266/p/9683297.html
Copyright © 2011-2022 走看看