extern "C"的理解

extern "C"的引入是为了解决C++函数重载的问题,C++之父在设计C++语言的时候,考虑到对C的兼容,引入了extern "C",使得在C++中能够无误地使用C的库函数(大部分的库函数都是由C编写的)


在编译期间,C和C++为函数生成修饰名的方式是不一样的,这一点可以认为是C++实现函数重载的机制,考虑这样一段C代码:

int fun(int x)
{
  return 0;
}

使用 /FAs 选项生成汇编代码,留意fun函数的修饰名:

; 这是使用C编译方式进行编译的

PUBLIC	_fun                 ; _fun是函数fun的修饰名
_TEXT	SEGMENT
_x$ = 8
_fun	PROC NEAR

; 3    : {

	push	ebp
	mov	ebp, esp

; 4    :   return x;

	mov	eax, DWORD PTR _x$[ebp]

; 5    : }

	pop	ebp
	ret	0
_fun	ENDP
_TEXT	ENDS
END


同样的代码,换成C++的编译方式,汇编代码如下:

PUBLIC	?fun@@YAHH@Z
_TEXT	SEGMENT
?fun@@YAHH@Z PROC NEAR                                  ; ?fun@@YAHH@Z 是 fun 函数的修饰名

; 12   : {

	push	ebp
	mov	ebp, esp

; 13   :   return 0;

	xor	eax, eax

; 14   : }

	pop	ebp
	ret	0
?fun@@YAHH@Z ENDP					; fun
_TEXT	ENDS
END


可见,同样的一段代码,C和C++编译方式区别还是很大的,特别是为函数生成修饰名的时候,因此这样的程序是有问题的:

/* fun.c */
int fun(int x)
{
  return x;
}
// test.cpp
#include <stdio.h>

extern int fun(int);

int main(void)
{
  printf("%d\n", fun(2));
  getchar();
  return 0;
}
提示的错误是:

原因是:fun是采用C的编译方式,编译器为其生成的函数修饰名是_fun,而在test.cpp文件中的fun函数采用的是C++编译方式,生成的修饰名是?fun@@YAHH@Z,在链接阶段,由于前后fun生成的修饰名不一致,导致重定向失败,所以就出错了!

而为了在C++中使用C编译方式,才引入了extern "C"技术(其实不光是这样,想想在项目中使用的库函数,大部分都是用C语言编译方式的),现在对上面的test.cpp代码进行改动:

// test.cpp
#include <stdio.h>

extern "C"
{
  extern int fun(int);
}

int main(void)
{
  printf("%d\n", fun(2));
  getchar();
  return 0;
}


重新编译,链接,程序运行正常了!

在extern int fun(int)外加入extern "C"进行声明,就告诉编译器fun函数是按C语言编译方式进行编译的,于是,编译器就为fun函数生成C方式的修饰名,对test.cpp使用/FAs选项,留意一下fun函数的修饰名:

EXTRN	_fun:NEAR
_DATA	SEGMENT
$SG529	DB	'%d', 0aH, 00H
_DATA	ENDS
_TEXT	SEGMENT
_main	PROC NEAR

; 10   : {

	push	ebp
	mov	ebp, esp
	push	ecx

; 11   :   printf("%d\n", fun(2));

	push	2
	call	_fun                     ; 现在fun函数的修饰名变成C方式了!
	add	esp, 4
	push	eax
	push	OFFSET FLAT:$SG529
	call	_printf
	add	esp, 8



  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值