当前位置: 代码迷 >> 综合 >> C 语言之 auto / register / static / extern
  详细解决方案

C 语言之 auto / register / static / extern

热度:90   发布时间:2023-10-14 23:13:15.0

文章目录

    • 说明
    • 图示说明
    • extern 详解
    • C++ 调用 C 详解
    • C 调用 C++ 详解

说明


  • auto
  • register
  • static
  • extern

图示说明


  1. auto 类型

C 语言之 auto / register / static / extern

  1. register 类型

C 语言之 auto / register / static / extern

  1. static 类型

C 语言之 auto / register / static / extern

C 语言之 auto / register / static / extern

  1. extern 类型

C 语言之 auto / register / static / extern

C 语言之 auto / register / static / extern

extern 详解


参考博客:c/c++:extern,extern "C"

参考博客:extern “C”的作用详解

参考博客:C++函数重载以及extern "C"

文章的精华如下:

  1. 情景一
// A.h
char a[2];// B.h
extern char * a;

错误!!!原因在于,指向类型 T 的指针并不等价于类型 T 的数组

  1. 情景二
// 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 在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。

  1. 情景三
// A.h
void foo(){
    }// B.h
extern void foo(){
    }

当函数提供方单方面修改函数原型时,如果使用方不知情继续沿用原来的 extern 申明,这样编译时编译器不会报错。但是在运行过程中,因为少了或者多了输入参数,往往会造成系统错误。目前业界针对这种情况的处理没有一个很完美的方案,通常的做法是提供方在自己的xxx_pub.h中提供对外部接口的声明,然后调用包涵该文件的头文件,从而省去 extern 这一步,以避免这种错误。

  1. 情景四
  #ifdef __cplusplus#if __cplusplusextern "C" {
    #endif#endif /* __cplusplus */// Todo...#ifdef __cplusplus#if __cplusplus}#endif#endif /* __cplusplus */

C++ 在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而 C 语言则不会,因此会造成链接时找不到对应函数的情况,此时 C 函数就需要用 extern “C” 进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。

  1. 情景五
// 模块 A 头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_Hint foo( int x, int y );#endif// 在模块 B 中引用该函数:
// 模块 B 实现文件 moduleB.cpp
#include "moduleA.h"
foo(2, 3);

正确,直接包含头文件调用

  1. 情景六
// 模块 A 头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_Hextern "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_Hextern 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_Hextern "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;
}
  相关解决方案