链接指示 重学extern关键字

C++程序有时候需要调用其他语言编写的函数,比如调用C语言编写的函数。如同调用C++函数一样,要调用其他语言编写的函数,也必须进行声明并确定形参列表和函数返回值。
对于其他语言编写的函数来说,编译器检查和调用的处理方式与普通C++函数一致,但是生成的代码有所区别
C++使用链接指示linkage directive 指出任意非C++函数所用的语言。
注:要想在c++代码中使用其他语言编写的代码,要求必须有权访问该语言的编译器,并且这个编译器与当前C++的编译器是兼容的。

项目包含一个test01.h头文件和包含主函数的cpp文件。欢迎指出错误。

/* test01.h */
#pragma once;
#include <iostream>
/*
extern "C++"{//这里不能写成extern "C++"{fun2(void),fun2(int);}的形式,因为本身就是c++的编译方式
	void fun2() {
		std::cout << "这是C++编写的函数fun2(void)" << std::endl;
		printf_s("这是C++编写的函数fun2(void)");
	}

	//这里fun(int a)如果不加extern "C++"的话,会报错。

	//在这里发生了函数重载,C++支持函数重载,C不支持。
	void fun2(int a) {
		std::cout << "这是C++编写的函数fun2(int a)" << std::endl;
		printf_s("这是C++编写的函数fun2(int a)");
	}
}
*/

void fun2(int a) {
	std::cout << "这是C++编写的函数fun2(void)" << std::endl;
	printf_s("这是C++编写的函数fun2(void)");
}

//这里fun(int a)如果不加extern "C++"的话,会报错。

//在这里发生了函数重载,C++支持函数重载,C不支持。
//void fun2(int a) {
//	std::cout << "这是C++编写的函数fun2(int a)" << std::endl;
//	printf_s("这是C++编写的函数fun2(int a)");
//}

/*主函数cpp*/
#include <iostream>
#include <vector>
#include <string>

//#include "test01.h"

using namespace std;

#ifdef __cplusplus
extern "C"
#endif // __cplusplus
void fun5() {
	cout << "注意看预编译的时候去掉预编译宏的效果" << endl;
}
/*
如果是按照c++的方式编译,则去掉预编译宏后 的效果,是告诉编译器fun5()函数按照C的方式生成代码
extern "C" void fun5() {
	cout << "注意看预编译的时候去掉预编译宏的效果" << endl;
}
*/
/*
C++程序有时候需要调用其他语言编写的函数,比如调用C语言编写的函数。如同调用C++函数一样,要调用其他语言编写的函数,也必须进行声明并确定形参列表和函数返回值。
对于其他语言编写的函数来说,编译器检查和调用的处理方式与普通C++函数一致,但是生成的代码有所区别。
C++使用链接指示linkage directive 指出任意非C++函数所用的语言。
注:要想在c++代码中使用其他语言编写的代码,要求必须有权访问该语言的编译器,并且这个编译器与当前C++的编译器是兼容的。
*/

//链接指示不能出现在类内或者函数体内。意思是在类内核函数体内不能使用extern
extern "C" {//编译器应该支持C语言的链接指示 也可以是extern "FORTRAN"
/*
gcd(a,b)==1说明a,b互质
辗转相除法,又称欧几里得算法,时间复杂度log2 N
*/
	size_t gcd(int n, int m) //这是一个求两个数最大公约数的函数,使用辗转相除法
	{
		if (m == n)return n;
		if (n > m) {
			int temp = n;
			n = m;
			m = temp;
		}//保证m是大值

		while (n>0)
		{
			int ret = m % n;
			m = n;
			n = ret;
		}
		return m;
	};
//此部分会生成c的代码,而不是cpp的代码
}

//这里不能写成extern "C++" 会报错,因为本身就是C++的编译方式
extern "C" {//告诉编译器,头文件test01.h按照C语言的方式进行编译
#include "test01.h"
/*
使用extern "C"告诉编译器头文件按照C语言的方式进行编译,如果在头文件中出现了函数重载,
编译器报:不允许重载函数的C链接
*/
}

//int fun1() {
//	extern "C" void f() {};//提示不允许使用链接规范
//}

void fun4(int a) {
	cout << "这是C++方式编译的fun4(int)函数" << endl;
}

//指向extern "C"的函数指针
extern "C" void(*pf)(int)=fun2;//pf指向一个C函数,该函数接收int,返回void
extern "C" void(*pf2)(int) = fun4;//没有报错。根据C++ Primer说C的函数指针只能接收C的函数地址,但是这里pf2接收了C++的fun4函数的地址。
int main() {
	fun2(0);
	//pf = &fun2;
	(*pf)(0);
	(*pf2)(0);
	pf = pf2;//没有报错,与Primer书上描述的不一致。
	(*pf)(0);
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值