• extern关键词声明 global variable & function


    extern关键词声明 global variable & function

    In fact, function is a special global variable. 因为函数的访问也是通过全局的address实现的。


    Global variable

    使用extern关键词的目的是:使全局变量能在别的源文件中使用。

    对于这个问题,有的人说不需要extern也能实现,例如:

    /*******************************
     * a.h
     *******************************/
    #ifndef _A_H_
    #define _A_H_
    
    int v = 1;  /* define a variable */
    
    #endif /* a.h */
    
    
    /*******************************
     * b.c
     *******************************/
    #include "a.h"
    
    void main(void ) 
    {
        v = 10; /* update value */
    }
    

    这样做有什么问题呢?是的,如果只有一个源文件include a.h,这时貌似不会出现什么问题。

    但是一旦有另一个d.c也需要用到global variable v,它也include了a.h,此时链接就会报错了

    /*******************************
     * d.c
     *******************************/
    #include "a.h"
    
    void func(void) {
        v = 20; /* also use v */
    }
    

    如果这时编译b.c和d.c,就会报multiple definition的错误。

    因为两个文件在preprocess时都会展开a.h,也就相当于在源文件添加了一行 int v = 1;的定义,那当两个obj文件链接时,肯定会发生multiple definition了。

    有一点需要注意的是当a.h仅定义 int v; 没有initialize时,GCC编译器的特性是对这些obj文件中没有initialize的变量自动添加extern属性。所以要对initialize v才能观察到multiple definition的结果!

    参考:https://www.cnblogs.com/Sorean/p/4709039.html


    另外,如果你不是C语言的新手,大概看到过类似最好避免在header中definition的要求,header中仅declaration!这是规范C语言编程的要求。


    是时候让extern出场了!

    解决此问题的办法是使用v的另外源文件中用extern再次declare一次。declare可以无限次,但是define只能一次。

    使用extern就无需多余的a.h了,而将global sharable variable定义在源文件a.c中,这更符合现代的应用场景。例如,上述project可以修改为:

    /*******************************
     * a.c
     *******************************/
    
    int v = 1;  /* define a variable */
    
    /*******************************
     * b.c
     *******************************/
    // #include "a.h" /* no need to include a.h */
    
    extern int v;
    
    void main(void ) 
    {
        v = 10; /* update value */
    }
    
    /*******************************
     * d.c
     *******************************/
    // #include "a.h" /* no need to include a.h */
    
    extern int v;
    
    void func(void) {
        v = 20; /* also use v */
    }
    

    这个方法简直太棒了,要注意,extern int v;仅是一个declare语句,正如上面所说,declare可以无限次!

    哪个源文件需要使用v就使用extern关键词declare一次即可。

    甚至,extern的作用域可以限制到function内,若在一个function内部使用extern declare一个external variable,这个全局属性仅在此function内有效!

    For function

    对于function,若我们想要在其它文件中调用,通常会通过包含头文件的方式。例如:

    在a.c中定义了一个function add(),若要在b.c中调用,我们会通过在a.h中声明此function

    /*******************************
     * a.h
     *******************************/
    #ifndef _A_H_
    #define _A_H_
    
    int add(int x,int y);
    
    #endif /* a.h */
    

    然后在b.c中 include<a.h>,就可以使用add function了。

    我们想过它的原理吗?

    对于这种特殊的global variable,我们在header中declare它的时候其实前面省略了extern关键词

    所以其它include此header的源文件才能使用add function,大概就是这个原因。


    那么,我们是不是可以这样试试:

    /*******************************
     * a.c
     *******************************/
    
    int add(int x,int y)
    {
        return x + y;
    }
    
    /*******************************
     * b.c
     *******************************/
    // #include "a.h"
    
    extern int add(int x, int y);
    
    void main(void ) 
    {
        printf("%d\r\n", add(1, 2));
    }
    

    哈哈,按照原理来说,当然也是可以的,这也就表示function和global variable本质上是类似的。

    However,在实际应用中我们很少这样用,因为一旦需要调用的函数很多,很难去一下子梳理每个函数来自哪个源文件(lll¬ω¬),不仅仅你过几天会忘记这些函数来自哪个源文件,对于接手此项目的下一位coder,这更是一场disaster!

  • 相关阅读:
    继承
    面向对象_封装练习
    ajax分页与组合查询配合使用
    Linq的分页与组合查询的配合使用
    发送邮件和数据导出
    GridView的使用
    母版页的使用
    DIV+CSS命名规范
    Ajax基础
    jQuery动画效果
  • 原文地址:https://www.cnblogs.com/bluettt/p/15075517.html
Copyright © 2020-2023  润新知