链接指示:extern “C”

作者: veaxen 分类: C/C++ 发布时间: 2017-08-01 15:01

C++程序有时需要调用其他语言编写的函数,最常见的是调用C语言编写的函数。像其他所有其他名字一样,其他语言中的函数名字也必须在C++中进行声明,并且该声明必须指定返回类型和形参列表。对于其他语言编写的函数来说,编译器检查其调用的方式与处理普通C++函数的方式相同,但是生成的代码有所区别。C++使用**链接指示**指出任意非C++函数所用的语言。

## 声明一个非C++的函数

链接指示可有两种形式:单个的或者复合的。链接提示**不能出现在类的定义或者函数定义的内部**。同样的链接提示**必须在函数的每个声明中都出现**。

举个例子,接下来的声明显示了cstring头文件的某些C函数是如何声明的:

“`

```"null"
//可能出现在C++头文件中的链接提示
//单语句链接指示
extern "C" size_t strlen(const char *);
...
//复合语句链接指示
exten "C" {
int strcmp(const char*,const char*);
char *strcat(char*,const char*);
}

```

```

链接指示的第一中形式包含一个关键字extern,后面是一个字符串字面值常量以及一个“普通的”函数声明。

其中的字符字面值常量指出了编写函数所用的语言。编译器应该支持对C语言的链接指示。此外,编译器也可能会支持其他语言的链接指示,如extern \"Ada\"、extern \"FORTRAN\"等。

## 链接提示与头文件

我们可以令链接指示后面跟上花括号括起来的若干函数的声明,从而一次性建立多个链接指示。花括号的作用是将适用于该链接指示的多个声明聚合在一起,否则花括号就会忽略,花括号中声明的函数名字就是可见的,就好像在花括号之外声明一样。

多重声明的形式可以应用于整个头文件。例如,C++的cstring头文件可能的形式如下:

```

```"null"
//复合语句链接指示
extern "C"{
#include
}

```

```

当一个#include指示被放置在复合链接指示的花括号中时,头文件中的所有普通函数声明都被认为是有链接指示的语言编写的。**链接指示可以嵌套**,因此如果头文件包含自带链接指示的函数,则该函数的链接不受影响。

## 指向extern \"C\"函数的指针

编写函数所用的语言是函数的一部分。因此,对于使用链接指示定义的函数来说,他的每个声明都必须使用相同的链接指示。而且,**指向其他语言编写的函数指针必须与函数本身使用相同的链接指示**:

```

```"null"
//pf指向一个C函数,该函数接收一个int返回void
extern "C" void (*pf)(int);

```

```

当我们使用pf调用函数时,编译器认定当前调用的是一个C函数。

必须指出:**指向C函数的指针与指向C++函数的指针是不一样的类型**。

不能用在执行初始化或者赋值操作后指向C++函数,反之亦然。就像其他类型不匹配的问题一样,如果我们试图在两个链接指示不同的指针之间进行赋值操作,程序会发生错误:

```

```"null"
void (*pf1)(int); //指向一个C++函数
extern "C" void (*pf2)(int); //指向一个C函数
pf1 = pf2; //错误:pf1和pf2的类型不同
//(有的编译器可能接收这样的操作,但严格讲的非法的)

```

```

当我们使用链接指示时,它不仅对函数有效,而且对作为返回类型或者形参类型的函数指针也同样有效:

```

```"null"
// f1是一个C函数,它的形参是一个指向C函数的指针
extern "C" void f1(void(*)(int));

```

```

这条声明语句指出f1是一个不返回任何值的C函数。它有一个类型是函数指针的形参,其中函数接收一个int形参返回为空。这个链接指示不仅对f1有效,对函数指针同样有效。当我们调用f1时,必须传给它一个C函数的名字或者指向C函数的指针。

因为链接指示同时作用于声明语句中的所有函数,所以如果我们希望给C++函数传入一个C函数的指针,则必须使用类型别名:

```

```"null"
//FC是一个指向C函数的指针
extern "C" typedef void FC(int);
//f2是一个C++函数
void f2(FC *);

```

```

## 重载函数与链接指示

链接指示与重载函数的相互做作用依赖于目标语言。如果目标语言支持重载函数,则为该语言实现链接指示的编译器很可能也支持重载这些C++函数。

**标准C语言不支持函数重载**,因此也就不难理解为什么一个C链接指示只能用于说明一组重载函数中的某一个了:

```

```"null"
//错误:两个extern "C"函数名字相同
extern "C" void print(const char*);
extern "C" void print(int);

```

```

如果在一组重载函数中有一个是C函数,则其余的必须都定义为C++函数。

- - - - - -

参考自《C++primer》第5版

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

一条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据