请选择 进入手机版 | 继续访问电脑版
MSIPO技术圈 首页 IT技术 查看内容

C++ extern

2023-07-13

  • extern ˈekstɜ n外面的;外来的;对外的

当extern与"C"在一起修饰变量或函数时

  • C++ 与 C 编译区别
    在C++中常在头文件见到extern "C"修饰函数,那有什么作用呢? 是用于C++链接在C语言模块中定义的函数。

C++虽然兼容C,但C++文件中函数编译后生成的符号与C语言生成的不同。因为C++支持函数重载,C++函数编译后生成的符号带有函数参数类型的信息,而C则没有。

例如 int add(int a, int b) 函数经过C++编译器生成.o文件后,add会变成形如 add_int_int 之类的, 而C的话则会是形如 _add , 就是说:相同的函数,在C和C++中,编译后生成的符号不同。

这就导致一个问题:如果C++中使用C语言实现的函数,在编译链接的时候,会出错,提示找不到对应的符号。此时extern "C"就起作用了:告诉链接器去寻找_add这类的C语言符号,而不是经过C++修饰的符号。

  1. 被 extern “C” 修饰的变量和函数是按照 C 语言方式编译和连接的
  2. extern “C” 的作用是让 C++ 编译器将 extern “C” 声明的代码当作 C 语言代码处理,可以避免 C++ 因符号修饰导致代码不能和C语言库中的符号进行链接的问题。
#ifdef __cplusplus
extern "C" {
#endif

void *memset(void *, int, size_t);

#ifdef __cplusplus
}
#endif

在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。所以使用extern "C"全部都放在于cpp程序相关文件或其头文件中。不过与C++调用C接口不同,C++确实是能够调用编译好的C函数,而这里C调用C++,不过是把C++代码当成C代码编译后调用而已。也就是说,C并不能直接调用C++库函数。

  • C++调用C函数:
//xx.h
extern int add(...)

//xx.c
int add(){
    
}

//xx.cpp
extern "C" {
    #include "xx.h"
}
  • C调用C++函数
//xx.h
extern "C"{
    int add();
}
//xx.cpp
int add(){
    
}
//xx.c
extern int add();

作用域扩展

  • 当 extern 不与"C"在一起修饰变量或函数时,如在头文件中:extern int g_Int;它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块或其他模块中使用,记住它是一个 声明不是定义 也就是说编译单元B要是引用编译单元A中定义的全局变量或函数时,它只要包含A的头文件即可,在编译阶段,模块B虽然找不到该函数或变量,但它不会报错,它会在链接时从模块A生成的目标代码中找到此函数。

  • 注意:在使用extern时候要严格对应声明时的格式,比如在一个源文件里定义了一个数组:char a[6];,在另外一个文件里用下列语句进行了声明:extern char *a;这样是不可以的。但这同时也就造成另一个问题:如果函数原型被单方面修改的话,调用方在不知情情况下进行调用,在编译阶段不会报错,但是在运行时会由于参数类型不匹配而出错,所以现在大多只在头文件中进行声明并使用#include头文件的方式来引入函数而非extern。

  • extern的常用用法:在源文件中声明了一个全局的变量,这个全局的变量如果要被引用,就放在头文件中并用extern来声明。

  • 作用域扩展用法:

//"externTest.h"
#pragma once
#include <iostream>

int _g_o = 100;

void _g_fun() {
    std::cout << "Hello, World!" << std::endl;
    _g_o = 999;
}



// main.cpp
#include <iostream>
//不引入头文件会编译报错。没有引入情况下, extern int _g_o = 1;  这样是可以的 取值为1
//引入头文件情况下,不需要给_g_o 赋值,能共享 externTest 文件中定义的值
#include "externTest.h"

extern int _g_o;
extern void _g_fun();

int main() {
        std::cout << "_g_o: "<< _g_o << std::endl;//输出100
    _g_fun(); //能正常调用外部文件的方法
    std::cout << "_g_o: "<< _g_o << std::endl;//输出999
    return 0;
}

相关阅读

热门文章

    手机版|MSIPO技术圈 皖ICP备19022944号-2

    Copyright © 2024, msipo.com

    返回顶部