返回 登录
0

C语言-进阶过渡—extern C问题

在android的external/sqlite/android目录,查看sqlite3_android.h的时候,发现

图片描述

what that means ?

(首先,涉及到条件编译,应该是和编译器有关;

涉及到__cplusplus宏,据我所知,应该和链接器ld也关,毕竟c和c++链接库的时候方式不同,链接的库类型不一样)

把问题搞清楚,先回顾一下extern:(和auto一样,是一种存储类型)

在马伟《改善C建议125》的第8个建议里面说了extern这个存储类型:(我简单概括一下)

函数外面定义的叫外部变量 (也是全局变量) —–引用它的文件是可以修改它的值的(很容易造成混乱)

                                                      -----生命周期(时间意义上)是整个程序的生存周期,作用域是文件作用域(声明的地方到文件尾)

函数内部定义的叫做内部变量(也就是局部变量)—–作用域在函数块儿内

常见的两个使用场景是:

使用先于,声明(在文件的后半部分才定义某个全局变量,却要在之前就定义的main或者其他函数中使用该变量,这个时候,使用的时候就要加上extern做声明),举例?略(又不是入门,所以不给案例)

一个源文件要引用另一个文件定义的全局的变量(自己懒得定义或者想共用一个传递&通信信息),这个时候引用该变量的文件就要加上extern关键字去声明引用(不用初始化,因为是全局变量,程序起来的时候,就已经初始化过了)—案例?略

外部函数:

上面是说的extern的变量,函数也是类似。

默认声明&定义的时候,只要不加上static,那么全局的函数或者变量都是extern的,即使你省略关键字。

这个需要验证一下,请看案例如下:(同目录下有俩文件,tmp.c和main.c)
图片描述
图片描述

注意,我并没有在main.c里面在预处理的时候include(包含) tmp.c相关声明&定义。

这里补充说一下static, 如果你去把全局变量或者全局函数定义成static的那么其生命周期不变,但是作用域就变成文件作用域了。

可以看下,还是上面的例子,我在tmp.c,也就是定义&声明的地方,故意加上static,编译看看

(因为是链接的时候做处理,所以gcc统一处理一下就可以了)

图片描述

我怎么去看是预处理还是链接的出问题的?

图片描述

上面就说明是链接阶段出问题(具体请参看gcc手册,跟你编译环境有关)

总结:

被引用的全局变量,在引用的地方加上extern外(仅仅是声明,并不分配空间!),还要求在定义的地方必须是extern的

                (默认就是extern存储类型,告诉编译器别人可以引用)

只引用一个函数的话,就没有去include相应的头文件,因为unix的哲学是kiss (keep it simple, and stupid)

extern说完了(告诉编译器外部模块可以引用的意思),再说说“C”,这个“C”不能单独理解,要和extern一起理解

为什么?

因为上面猜想,不是编译阶段,就是链接阶段的问题,实际上呢?both!

经过在网上查看了一下资料,并亲手动手实验了一下(编译器gcc 4.9,这里试验要写一个cpp才可以,用到g++,不贴出来了),

确认了是为了在链接的时候能让链接器ld找到外部函数或者变量的定义,但是链接的时候c和c++不同,说明编译的时候,c和c++的编译处理规则就不同。

(符号表中找不到,ld肯定报错啊)

这里涉及到编译&链接等知识,

我不展开,就说理解(下面有亲自试验):(请注意到一个细节,一般是Cpp程序中才会出现extern “C”)

c++毕竟涉及到的特性多,所以实际编译出来的代码的话,会有更多符号(符号表更大),所以在C++文件中

混入C代码(函数,变量,库)的时候,要调用原生的C,并且想用C的编译&链接方式处理的那些代码的话,就要写上extern “C”,定义和引用的位置都需要。

(注意extern “C”只出现在cpp程序中,c程序,根本不需要extern “C” 只需要extern就可以了,即定义的时候省略extern关键字就是extern类型,而引用的时候加上extern即可,而不必extern “C”)

请看头文件和它的实现文件(注意这是cpp文件)

图片描述

图片描述

总结?

关于 extern “C”类型的变量和函数的定义&引用,无非是要在cpp程序中引入c的原生代码(c的代码编译链接当然也按c的方式来咯)。

所以你就把extern “C”理解成一种“在C++环境下的定义和引用原生C的全局变量&函数的”类型。

(毕竟像C++这种本来是面向对象特性的语言,偏偏要照顾C这种带外部变量和函数的语言,一切都是历史原因,多说无益啊)

欢迎学习c语言c++的小伙伴进c交流学习群552838805教程和各种资料和工具都放群里了欢迎来和小伙伴们一起交流学习进步走上人生巅峰。

评论