C语言存储方式和作用域(2)-关键字的使用

一.概述:

            前面总结了变量的类型,不同类型的变量有着不同的存储类型、不同的生命周期、不同的作用域.

         在C语言中没有其他高级语言的public private等修饰符,来限定变量和函数的有效范围,但是却有两个类似的关键字能达到类似的效果:

        extern 和 static.


二、extern与函数:

           先理解两个概念:

            1.外部函数:如果在当前文件中定义的函数允许其他文件访问、调用,就称为外部函数.(注意:C语言规定,不允许有同名的外部函数).

            2.内部函数:如果在当前文件中定义的函数不允许其他文件访问、调用,只能在内部使用,就称为内部函数。(C语言规定不同的源文件可以有同名的内部函数,并且互不干扰)


      

    开始使用:

注意:如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用b.obj中定义的一个函数。将这些相关联的目标文件链接在一起后才能生成可执行文件。


比如:


第一步创建one.c程序(源程序)


        

第二步main应该怎么调用呢?

    如果直接调用one()函数会报错.    但是在Xcode中,不会报错,抛出警告,但是在标准的c语言编译器中,一定会报错。



   那么就直接导入#include"One.h"行了呗。


            这个看上去思想是对的,但是编译的时候会报错,为什么呢?


因为在链接的时候会报错。我们已经在one.c中定义了one函数,现在又在main.c中定义one函数(从one.c那里拷贝one文件内容),C语言规定不允许有同名的外部函数,链接的时候链接器会发现在one.obj和main.obj中定义了同一个函数,会直接报错,Xcode中的错误信息是这样的:


duplicate symbol _one是说one这个标识符重复了,    linker是指链接器。


上面的两种想法都是不可行的,其实思路是一致的。


要想让main函数知道one函数的存在。


确的做法应该是在main函数前面对one函数进行提前声明(看清楚,是声明,不是定义,定义和声明是两码事)。


extern关键字对函数的作用:用来定义和声明一个外部函数,但是extern又跟auto一样,完全可以省略。于是,我们可以简化成上面这样。

如果你觉得标准点 可以 在void 前面加上extern.



现在可以正确调用了:






再补充:

为了模块化地开发,我们会把one函数的声明写到另一个头文件中。


当然文件名最好有意义,所以叫one.h,方便识别,在这.h文件中记得要进行宏定义判断防止多次拷贝


以后谁想调用这个one函数,就导入one.h头文件就行了(Xcode会默认帮忙创建这个one.h文件...并且Xcode 会自动生成宏定义判断防止多次拷贝,只需要声明函数




要是改为把onc.c文件函数改为内部函数:


直接给出报错,外部文件不能访问其他文件内部函数.


三.内部函数:

#include<stdio.h>
static void test();
int main(){
test();
return 0;
}
static void test(){
printf("调用了test函数");
}


总结:

1.extern:在定义函数时,如果在函数最左边加上关键字 extern,则表示此函数是显性的外部函数,可以供其他文件调用。如果定义函数省略extern,则表示隐性的外部函数.


在一个文件中要调用其他文件中的外部函数,则需要在当前文件中用extern声明该外部函数,然后可以调用。可以省略extern。


2.static:在定义函数时,在函数的最左边加上static可以把该函数声明为内部函数(又叫静态函数),这样该函数就只能在其定义所在的文件中使用。如果在不同的文件中有同名的内部函数,则互不干扰。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值