说明
- auto
- register
- static
- extern
图示说明
- auto 类型
- register 类型
- static 类型
- extern 类型
extern 详解
参考博客:extern “C”的作用详解
参考博客:C++函数重载以及extern "C"
文章的精华如下:
- 情景一
// A.h
char a[2];
// B.h
extern char * a;
错误!!!原因在于,指向类型 T 的指针并不等价于类型 T 的数组
- 情景二
// A.h
int i; // 全局变量
// B.h
int i; // 全局变量
错误!!!原因在于,在编译阶段,各个文件中定义的全局变量相互是透明的,编译A时觉察不到B中也定义了 i,同样,编译B时觉察不到A中也定义了 i。但是到了链接阶段,要将各个文件的内容“合为一体”,因此,如果某些文件中定义的全局变量名相同的话,在这个时候就会出现重复定义的错误。
正确做法是在 B.h 中的 int i; 前面加上 extern 。extern int i; 仅仅是一个变量的声明,其并不是在定义变量i,并未为 i 分配内存空间。变量 i 在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。
- 情景三
// A.h
void foo(){}
// B.h
extern void foo(){}
当函数提供方单方面修改函数原型时,如果使用方不知情继续沿用原来的 extern 申明,这样编译时编译器不会报错。但是在运行过程中,因为少了或者多了输入参数,往往会造成系统错误。目前业界针对这种情况的处理没有一个很完美的方案,通常的做法是提供方在自己的xxx_pub.h中提供对外部接口的声明,然后调用包涵该文件的头文件,从而省去 extern 这一步,以避免这种错误。
- 情景四
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
// Todo...
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
C++ 在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而 C 语言则不会,因此会造成链接时找不到对应函数的情况,此时 C 函数就需要用 extern “C” 进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。
- 情景五
// 模块 A 头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif
// 在模块 B 中引用该函数:
// 模块 B 实现文件 moduleB.cpp
#include "moduleA.h"
foo(2, 3);
正确,直接包含头文件调用
- 情景六
// 模块 A 头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y ); // 这里加了 extern "C"
#endif
// 在模块 B 中引用该函数:
// 模块 B 实现文件 moduleB.cpp
#include "moduleA.h"
foo(2, 3);
错误!!!B 模块中将 foo(int, int) 转化为了 foo_int_int() 函数,但是在 A 中没有这样的函数!!!
C++ 调用 C 详解
// C 语言头文件:cExample.h
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x, int y);
#endif
// C 语言实现文件:cExample.c
#include "cExample.h"
int add( int x, int y ){
return x + y;
}
// C++ 实现文件,调用 add()方法:cppFile.cpp
extern "C" {
#include "cExample.h"
}
int main(int argc, char *argv[]){
add(2, 3);
return 0;
}
C 调用 C++ 详解
// C++ 头文件 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif
//C++ 实现文件 cppExample.cpp
#include "cppExample.h"
int add( int x, int y ){
return x + y;
}
// C 实现文件:cFile.c
// 这样会编译出错:#include "cppExample.h"
extern int add( int x, int y );
int main( int argc, char* argv[] ){
add( 2, 3 );
return 0;
}