在很多C/C++头文件中,你可能会经常看到使用extern “C”{}包含起来的代码。这种语法的存在是为了使C和C++代码能够兼容。兼容?C++对C本来不就是兼容的吗?确实,在语法层面,C++支持几乎所有C语法。但这里的兼容是目标文件或者库级别的兼容,包括两种情况下的兼容。一种是,在C++代码中调用已经存在的C代码写成的库;另一种是,使用C编写代码,而希望这些代码能够使C++可以调用。
若想继续讨论extern “C”,就不得不提name mangling。
我们知道,相比C,C++支持函数重载,支持命名空间,支持类以及成员函数。函数重载允许我们声明名字相同参数不同的函数,命名空间(namespace)和类为名字(或者说符号)划分了不同的域使得我们可以在不同域中使用完全相同的名字。而为了实现这种特性,C++就使用了name mangling。即是说,C++编译器在编译C++文件时,把每一个函数名“打乱”成与函数所在域、参数类型、调用约定相关的另外一个名字(因为汇编级别的代码中,所有符号都在同一个域)。由于C中并不存在这些特性,所以通常C编译器并不对符号进行mangling。
由于C++中这种mangling的存在,使C和C++在符号上不统一,无法直接相互调用。比如C中有这样一个函数,
//~ add.h
int add(int, int);
//~ add.c
int add(int a, int b)
{
return a + b;
}
使用gcc编译add.c。然后在C++代码中直接调用add函数,
//~ main.cpp
#include <add.h>
int main()
{
int a = add(0, 1);
return 0;
}
这样编译main.cpp,
$ gcc -c add.c
$ g++ -c main.cpp
$ g++ main.o add.o -o main
main.o: In function `main':
main.cpp:(.text+0x13): undefined reference to `add(int, int)'
collect2: ld returned 1 exit status
错误提示add(int, int)为找到。将main.cpp编译成汇编后,查看调用add的代码为
movl $1, %esi # 参数入栈
movl $0, %edi # 参数入栈
call _Z3addii # 调用add, 注意符号
movl %eax, -4(%rbp) # 返回值赋给int a
解决这种情况的方法就是使用extern “C”,在add.h中,把add的声明放入extern “C”{}中。这样,g++就不会对add进行mangling,链接器就会在add.o中找到add并链接到main.o。通常,C代码的头文件(包括libc的头文件,比如string.h)中,函数的声明通常是这样的,
//~ add.h
#ifdef __cplusplus
extern "C" {
#endif
int add(int, int);
#ifdef __cplusplus
}
#endif
这样一来,如果是C代码包含add.h,那么将是直接包含add函数的声明。如果是C++代码包含add.h,那么extern “C”就将会被引入。关于name mangling,请参考这里,还有这里。
转载自:
http://www.dutor.net/index.php/2010/09/extern-c/
分享到:
相关推荐
关于extern C 的超级详解。解决以后所有包含extern C 的代码。
extern C 对你会有帮助的!!!
C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言, C++保留了一部分过程式语言的特点(被世人称为“不彻底地...
自己整理的关于extern c的用法,extern c虽不是大问题,但在面试中经常会碰到,希望对大家有所帮助。
详细介绍extern "C"的用法,有可运行的demo说明。可以深入掌握c与c++组合开发注意事项
C++语言extern C浅析
extern C的详细解释及使用方法,word版
c++/c中 externC. ifndef define endif 的用法
关于extern “C”的作用和意思,网上资料已经有很多了(我也参考了几篇),不过我还是觉得有必要自己总结一下,毕竟“好记性不如烂笔头”嘛~~
Extern_C,讲述extern的用法,和要注意的事项
2、extern C作用 链接指示符extern C 如果程序员希望调用其他程序设计语言尤其是C 写的函数,那么调用函数时必须告诉编译器使用不同的要求,例如当这样的函数被调用时函数名或参数排列的顺序可能不同,无论是C++...
如果想要取得尽量好的与平台无关性,则在.h文件头加入extern "C",强制编译器以C方法编译.cpp的文件,生成的文件名不会像.cpp那样给函数加上一堆附加信息。这样其他的编译器也可能识别他。但是这种方法只适合没有...
C语言extern使用方法总结,简单总结,请指教!
extern在C语言项目文件组织中的用法,非常经典
vc 用ado连接access数据库 自己整理的希望大家有用
C语言中extern关键字详解.docx ,C语言中extern关键字详解.docx
qt调用c语言代码(c语言的代码写在c文件中)
extern 'C' 详解
extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义