zoukankan      html  css  js  c++  java
  • 黑马程序员--C语言基础之--extern、static详解

    ------IOS培训期待与您交流! -------

    一、函数中的extern和static

    extern修饰的函数叫做外部函数,static修饰的函数叫做内部函数。

    外部函数:在某个源文件中定义的函数允许其他源文件访问,就称为外部函数。完整的定义是要加上extern关键字,但默认是可以省略的。

    内部函数:在某个源文件中定义的函数不允许其他源文件访问,就称为外部函数。内部函数用static修饰。

    1、extern

    以下的两个源文件中,main.c和test.c,test.c中定义了外部函数test(),main.c调用test():

        /* 
        test.c 
        */  
        //外部函数的完整定义  
        extern void test()  
        {  
            printf("调用了test函数");  
        }  
          
        //默认情况下,函数都是外部函数,可以省略extern  
        void test1()  
        {  
            printf("调用了test1函数");  
        }  

    main.c想要访问test.c定义的外部函数,必须先声明该函数,不能#include test.c源文件,#include test.c將会把test.c的内容复制一份到main.c,

    这将导致test()函数的重复定义,链接时会报错。

        /* 
        main.c 
        */  
        //main.c中想要访问test()函数,得先声明该函数,应该使用extern关键字,表示引用其他源文件的外部函数 
    //当然,extern也可以省略 extern void test(); //声明test函数 int main() { test(); return 0; }

    2、static

    从上面的例子可以看出,test.c中定义的test函数是可以被其他源文件访问的。

    其实有时候,我们可能想定义一个"内部函数",也就是不想让其他文件访问本文件中定义的函数。这个非常简单,只需要在定义函数的时候加个static关键字即可。

    如下所示

     
        /* 
        test.c 
        */  
        //内部函数的定义  
        static void test()  
        {  
            printf("调用了test函数");  
        }  

    此时,这个程序是可以编译成功的,因为我们在main函数前面声明了test函数(函数的声明和定义是两码事)。但是链接的时候,出现错误,test函数没有被定义。

    这是因为test函数是test.c的内部函数,不允许其他文件访问,链接器找到不到test函数,就报错了。

    3、总结

    (1)、extern:在定义函数时,如果用extern修饰,则表示此函数是外部函数,能够被其他源文件访问。如果省略extern,默认也是外部函数。

    如果当前源文件想要访问另一个源文件定义的外部函数,则需要在当前文件中用extern声明该外部函数,这里的extern也可以省略。

    (2)、static:在定义函数时,在函数的最左边加上static可以把该函数声明为内部函数(又叫静态函数),这样该函数就只能在其定义所在的文件中使用。

    static也可以用来声明一个内部函数。

    二、变量中的extern和static

    C语言中,一个变量只有先定义或者声明了,才能被后面的函数访问。

    extern一般用来声明变量,也可以用来定义变量,如果用来定义变量,编译器会发出警告,所以最好不用extern定义变量。static只能用于定义变量。

    1、extern

    在当前源文件定义了一个变量int a,可以用extern int a声明该变量。

        int a ;    //定义变量  
        int main()  
        {  
            extern int a;    //声明该变量。当然,a是全局变量,在前面已经定义了,现在可以不用声明直接使用 
    printf("a=%d ",a);
    return 0; }
     
        int main()  
        {  
            extern int a;    //此时必须声明该变量,否则报错,没有定义变量a  
    printf("a=%d ",a);
    return 0; }
    int a; //定义变量

    在其他源文件定义了一个全局变量int a,当前源文件想要访问变量a,必须用extern int a声明该变量之后,才能使用该变量。

        //test.c  
        int a ;    //定义变量  
        //main.c  
        int main()  
        {  
            extern int a;    //此时必须声明该变量,否则报错,没有定义变量a  
    printf("a=%d ",a);
    return 0; }

    在同一个源文件,能够重复定义相同的变量;它们实质上是一个变量。但是,不能多次定义初始化同一个变量。

        int a; //重复定义变量a,并且都没有初始化  
        int a;  
          
        int b;  
        int b = 1;  //重复定义变量b,只初始化一次  
          
        /* 
        int c = 1;  //多次定义并且初始化,则会报错 
        int c = 2 
        */  
        int main()  
        {  
            a = 1;  
    printf(
    "a=%d ",a);
    return 0; }
    int a;

    在不同的源文件,也能够重复定义相同的变量;它们实质上是一个变量。但是,不能多次定义初始化同一个变量。

        //test.c  
    int a ;
    int b = 1;
    //int c = 1;
        //main.c  
    int a; //重复定义变量a,没有初始化
    int b; //重复定义变量b,但是只初始化一次
    //int c = 1; //重复定义初始化变量c,报错
    int main() { printf("a=%d ",a);
    return 0;
    }

     

    不能只声明变量,不定义变量。

        //main.c  
    extern int a; //声明变量a
    int main() { printf("a=%d ",a); //没有变量a的定义,会报错
    return 0;
    }

    2、static

    static定义的全局变量不能被其他源文件访问,只能被当前源文件访问。

        //test.c  
    static int a; //静态全局变量,只能在本文件访问
    void test() { a = 10; }
        //main.c  
    extern int a; //声明变量a
    int main() { printf("a=%d ",a); //会报错,因为在test.c,和main.c中找不到变量a的定义
    return 0; }

    3、总结

    (1)extern:可以用来声明一个全局变量,但是不能用来定义变量。

    (2)默认情况下,一个全局变量是可以供多个源文件共享的,也就说,多个源文件中同名的全局变量都代表着同一个变量。

    (3)如果在定义全局变量的时候加上static关键字,此时static的作用在于限制该全局变量的作用域,只能在定义该全局变量的文件中才能使用,

    跟其他源文件中的同名变量互不干扰。

  • 相关阅读:
    [Git & GitHub] 利用Git Bash进行第一次提交文件
    Linux下 Unison 实现文件双向同步
    Linux SSH使用公钥私钥实现免登陆
    SSH自动断开连接的原因
    hosts.deny 和hosts.allow 配置不生效
    bind启动时提示953端口被使用
    Linux查询系统配置常用命令
    Linux 查硬件配置
    BIND rndc—使用说明
    rndc 错误解决 和 远程配置
  • 原文地址:https://www.cnblogs.com/waterfox/p/4370537.html
Copyright © 2011-2022 走看看