extern "C"——用“C”来规约在C++中用C的方式进行编译和链接

C++中的extern “C”用法详解

    extern "C"表明了一种编译规约,其中extern是关键字属性,“C”表征了编译器链接规范。对于extern "C"可以理解成在C++/C中的混合编程的编译指令。用“C”来规约在C++中用C的方式进行编译和链接。

extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。让我们来详细解读这两重含义。

1.    被extern"C"限定的函数或变量是extern类型的;

2.    extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量是一个已经定义的外部变量或函数,有了此声明,就可以从声明处起,合法的使用该变量或函数对于extern变量来说,仅仅是一个变量的声明,其并不是在定义分配内存空间。记住,下列语句:extern int a;仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间类型名int可以省略不写变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。

通常,也可以在模块A的头文件中对本模块A提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。而且编译阶段,外面是找不到该函数的,但是不报错。link阶段会从定义模块生成的目标代码中找到此函数。

与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。从代码到可执行程序需要经过编译和链接两个过程,其中编译阶段会做语法检测,代码展开,另外它还会做一件事,就是将变量转成符号,链接的时候其实是通过符号来定位的。编译器在编译C和C++代码时,将变量转成符号的过程符号名称是不同的,混合编程在链接时就会出现找不到函数的现象。例如,假设某个函数的原型为:

void foo( int x, int y );

该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangledname”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y)编译生成的符号是不相同的,后者为_foo_int_float。

这样也很容易理解为什么C++支持函数重载而C不支持了,因为C++将函数修饰为符号时把函数的参数类型加进去了,而C却没有,所以在C++下,即便函数名相同,只要参数不同,它们的符号名是不会冲突的

(1)在C++中引用C语言中的函数,需要在C++头文件里加extern “C”,否则C++编译的时候会找不到符号

/* c语言头文件:cExample.h */


1

2

3

4

#ifndef C_EXAMPLE_H

#define C_EXAMPLE_H

extern int add(int x,int y);    //对其外部函数指定为extern

#endif

/* c语言实现文件:cExample.c */


1

2

3

4

5

#include "cExample.h"

int add( int x, int y )

{

   return x + y;

}

// c++实现文件,调用add:cppFile.cpp


1

2

3

4

5

6

7

8

9

extern "C"  //采用C编译器编译的C语言代码段

{

   #include "cExample.c" 

}

int main(int argc, char* argv[])

{

   add(2,3);

   return 0;

}

 

(2)在C中引用C++语言中的函数,C++的头文件需添加extern "C",但是在C语言中不能直接引用声明了extern "C"的该头文件,应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。

1. 在C++的.h文件中用extern “C”{}声明将被C程序使用的函数

//C++头文件 cppExample.h


1

2

3

4

#ifndef CPP_EXAMPLE_H

#define CPP_EXAMPLE_H

extern "C" int add( int x, int y );  //采用C编译器编译的C语言代码段

#endif

2. 在C++的.cpp文件中实现上面的函数

//C++实现文件 cppExample.cpp


1

2

3

4

5

#include "cppExample.h"

int add( int x, int y )

{

    return x + y;

}

3. 在.c文件中用extern声明要使用的C++函数

// C实现文件 cFile.c    注意:切不可在.c文件中包含C++的.h文件,那样编译无法通过

/* 这样会编译出错:#include "cppExample.h" */


1

2

3

4

5

6

extern int add( int x, int y );    //仅将C文件中将C++中定义的extern "C"函数声明为extern类型

int main( int argc, char* argv[] )

{

add( 2, 3 );

return 0;

}

 

时间: 2024-10-03 22:55:44

extern "C"——用“C”来规约在C++中用C的方式进行编译和链接的相关文章

C、C++编译,链接,extern链接

1 //b.cpp 2 3 #inlcude <iostream> 4 5 void b() 6 { 7 std::cout<<"fun b"; 8 } 9 10 //a.cpp 11 extern void b(); 12 13 int main() 14 { 15 b(); 16 return 0; 17 } 18 19 //makefile 20 testA: a.o b.o 21 g++ -o testA a.o b.o 22 23 clean: 24

extern “C”的作用详解

extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码.加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的.由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名:而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般之包括函数名. 这个功能十分有用处,因为在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了

C++ 调用C语言、extern &quot;C&quot;、__cplusplus关键字

——C++编译器完全兼容C语言的编译方式.(但是得有源代码) ——C++编译器会优先使用C++的编译方式进行编译 ——extern "C" 关键字能够强制C++编译器进行C方式的编译 学习目标:实现C语言与C++之间的互相调用 学习 extern "C" {} 关键字 学习 __cplusplus标准宏 实验一.通过C++调用C编译器编译出来的 .o 文件 (extern "C" 关键字使用) 1.创建文件:add.c int add(int a

专题一经典问题解析-7

一.const和引用的疑惑 #include <stdio.h> int main() { const int x = 1; const int& rx = x; int& nrx = const_cast<int&>(rx); nrx = 5; printf("x = %d\n", x); printf("rx = %d\n", rx); printf("nrx = %d\n", nrx); pr

Linux下编译程序时,经常会遇到“undefined reference to XXX” 报错,

Linux下编译程序时,经常会遇到“undefined reference to XXX” 报错, 这里总结一些可能的原因和解决方案,给需要的朋友: 说道undefined reference error,先提一下Linux gcc链接规则: 链接的时候查找顺序是: -L 指定的路径, 从左到右依次查找 由 环境变量 LIBRARY_PATH 指定的路径,使用":"分割从左到右依次查找 /etc/ld.so.conf 指定的路径顺序 /lib 和 /usr/lib (64位下是/lib

Lua_第23章 C API 纵览

第23章 C  API 纵览 Lua是一个嵌入式的语言,意味着 Lua 不仅可以是一个独立运行的程序包也可以是一个用来嵌入其他应用的程序库.你可能觉得奇怪:如果 Lua 不只是独立的程序,为什么到目前为止贯穿整本书我们都是在使用 Lua 独立程序呢? 这个问题的答案在于 Lua 解释器(可执行的 lua).Lua解释器是一个使用 Lua 标准库实现的独立的解释器,它是一 个很小的应用(总共不超过500 行的代码).解释器负责程序和使用者的接口:从使用者那里获取文件或者字符串,并传给 Lua 标准

&quot;undefined reference to&quot; 多种可能出现的问题解决方法

最近在Linux下编程发现一个诡异的现象,就是在链接一个静态库的时候总是报错,类似下面这样的错误: (.text+0x13): undefined reference to `func' 关于undefined reference这样的问题,大家其实经常会遇到,在此,我以详细地示例给出常见错误的各种原因以及解决方法,希望对初学者有所帮助. 1.  链接时缺失了相关目标文件(.o)     测试代码如下: 然后编译. gcc -c test.c gcc –c main.c 得到两个 .o 文件,一

C and C++ 如何嵌套使用

1. 要知道extern "C"的含义: (1) extern是C/C++中表明函数和全局变量作用范围的关键字, 该关键字表明其申明的函数和变量可以在本模块或者其他模块中使用. (2) “C” 为了使的C/C++遵守同一个编译和链接的约定. 例如:指定strcpy()根据c的编译和链接方法,extern "C" char* strcpy(char *, const char*); (3) extern 是一个申明,而不是定义一个变量 extern “C”表示按照c的

vs2010环境下生成dll文件

vs2010环境下生成dll文件 1,新建win32工程,选中DLL项目,如下图:2,分别添加头文件和cpp文件 #ifndef LIB_H#define LIB_Hextern "C" int _declspec(dllexport)add(int x,int y);    // 声明为C编译.链接方式的外部函数#endif #include "stdafx.h"int add(int x,int y){    return x+y;} 3,新建win32控制台工