zoukankan      html  css  js  c++  java
  • 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!

  • 相关阅读:
    UVALive 6909 Kevin's Problem 数学排列组合
    UVALive 6908 Electric Bike dp
    UVALive 6907 Body Building tarjan
    UVALive 6906 Cluster Analysis 并查集
    八月微博
    hdu 5784 How Many Triangles 计算几何,平面有多少个锐角三角形
    hdu 5792 World is Exploding 树状数组
    hdu 5791 Two dp
    hdu 5787 K-wolf Number 数位dp
    hdu 5783 Divide the Sequence 贪心
  • 原文地址:https://www.cnblogs.com/bluettt/p/15075517.html
Copyright © 2011-2022 走看看