首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >一个名字或类型有某种语言联系意味着什么?

一个名字或类型有某种语言联系意味着什么?
EN

Stack Overflow用户
提问于 2011-04-23 11:29:20
回答 7查看 2.4K关注 0票数 40

根据(c) ANSI ISO/IEC 14882:2003,第127页:

连杆规格嵌套。当连接规范嵌套时,最内部的一个决定语言。链接规范没有建立作用域。链接-规范只能出现在命名空间范围(3.3)中。在链接规范中,指定的语言链接适用于由声明引入的所有函数声明器、函数名称和变量名称的函数类型。

代码语言:javascript
运行
复制
extern "C" void f1(void(*pf)(int));
// the name f1 and its function type have C language
// linkage; pf is a pointer to a C function

extern "C" typedef void FUNC();
FUNC f2;
// the name f2 has C++ language linkage and the
// function's type has C language linkage

extern "C" FUNC f3;
// the name of function f3 and the function's type
// have C language linkage

void (*pf2)(FUNC*);
// the name of the variable pf2 has C++ linkage and
// the type of pf2 is pointer to C++ function that
// takes one parameter of type pointer to C function

这一切意味着什么?例如,f2()函数有哪些链接,C或C++语言链接?

正如@Johannes Schaub所指出的,对标准中的含义没有真正的解释,因此在不同的编译器中可以对其进行不同的解释。

请解释对象文件中的不同之处:

  • 一个函数的名称与C语言链接和C++语言链接。
  • 使用C语言链接和C++语言链接的函数类型。
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2011-05-19 14:56:28

语言链接是指C++non-C++代码片段之间的链接。通常,在C++程序中,所有函数名、函数类型甚至变量名称都具有默认的C++语言链接。

C++对象代码可以链接到使用其他源代码(如C)生成的另一个对象代码,该对象代码使用预定义的链接说明符。

您必须知道name mangling的概念,它编码函数名、函数类型和变量名,以便为它们生成唯一的名称。这允许链接器区分公共名称(如函数重载的情况)。当将C模块与用C++编译器编译的库或对象文件链接时,不需要名称损坏。为了防止这种情况下的名称损坏,使用了链接说明符。在这种情况下,extern "C"是链接说明符。让我们举一个例子(c++代码提到了这里):

代码语言:javascript
运行
复制
typedef int (*pfun)(int);  // line 1
extern "C" void foo(pfun); // line 2
extern "C" int g(int)      // line 3
...
foo( g ); // Error!        // line 5

第1行声明pfun指向一个C++函数,因为它缺少链接说明符。

因此,第2行将foo声明为一个C函数,它接受指向C++函数的指针。

第5行尝试使用指向g、C函数和错误匹配类型的指针调用foo。

函数名称链接中的差异:

让我们使用两个不同的文件:

一个带有extern "c"链接(file1.cpp):

代码语言:javascript
运行
复制
#include <iostream>
using namespace std;

extern "C"
{
void foo (int a, int b)
{
    cout << "here";
}
}

int main ()
{
    foo (10,20);
    return 0;
}

一个没有extern "c"链接(file2.cpp):

代码语言:javascript
运行
复制
#include <iostream>
using namespace std;

void foo (int a, int b)
{
    cout << "here";
}

int main ()
{
    foo (10,20);
    return 0;
}

现在编译这两个并检查objdump。

代码语言:javascript
运行
复制
# g++ file1.cpp -o file1
# objdump -Dx file1

# g++ file2.cpp -o file2
# objdump -Dx file2

使用extern "C“链接,函数foo没有名称损坏。因此,任何正在使用它的程序(假设我们利用它创建一个共享库)都可以直接调用foo (带有像dlsymdlopen这样的助手函数),而无需考虑任何名称损坏效应。

代码语言:javascript
运行
复制
0000000000400774 <foo>:
  400774:   55                      push   %rbp
  400775:   48 89 e5                mov    %rsp,%rbp
....
....
  400791:   c9                      leaveq 
  400792:   c3                      retq   

0000000000400793 <main>:
  400793:   55                      push   %rbp
  400794:   48 89 e5                mov    %rsp,%rbp
  400797:   be 14 00 00 00          mov    $0x14,%esi
  40079c:   bf 0a 00 00 00          mov    $0xa,%edi
  4007a1:   e8 ce ff ff ff          callq  400774 <foo>
  4007a6:   b8 00 00 00 00          mov    $0x0,%eax
  4007ab:   c9                      leaveq 

另一方面,当不使用extern "C"时,func:foo会被一些预定义规则(编译器/链接器所知)破坏,因此应用程序不能直接从它调用它,将名称指定为foo。但是,如果需要,您可以使用损坏的名称(本例中是_Z3fooii)来调用它,但是没有人使用它是出于明显的原因。

代码语言:javascript
运行
复制
0000000000400774 <_Z3fooii>:
  400774:   55                      push   %rbp
  400775:   48 89 e5                mov    %rsp,%rbp
 ...
...
  400791:   c9                      leaveq 
  400792:   c3                      retq   

0000000000400793 <main>:
  400793:   55                      push   %rbp
  400794:   48 89 e5                mov    %rsp,%rbp
  400797:   be 14 00 00 00          mov    $0x14,%esi
  40079c:   bf 0a 00 00 00          mov    $0xa,%edi
  4007a1:   e8 ce ff ff ff          callq  400774 <_Z3fooii>
  4007a6:   b8 00 00 00 00          mov    $0x0,%eax
  4007ab:   c9                      leaveq 
  4007ac:   c3                      retq   

对于这个特定的主题,此页也是很好的读物。

一篇很好而且解释清楚的关于调用约定的文章:demystified.aspx

票数 18
EN

Stack Overflow用户

发布于 2011-05-18 08:22:41

“名称f2有C++语言链接”在C++语言链接中不仅定义了函数的名称,而且定义了it参数的类型和返回值。在本例中,您有: void f2( void );但是您可以用它定义:void f2(int a);没有冲突,因为链接会将它们看作不同的类型,这在C语言中是无法做到的。

“函数的类型有C语言链接”,我不知道细节,但我知道它的高层次。基本上,它使C++编译的函数可以从C链接到C,如果我正确地记得C和C++中参数传递给函数的方式是不同的。在这种情况下,函数f2将像C编译器那样传递参数。这样,函数就可以从C和C++连接起来。

票数 2
EN

Stack Overflow用户

发布于 2011-05-19 15:21:40

代码语言:javascript
运行
复制
extern "C" typedef void FUNC();
FUNC f2;
// the name f2 has C++ language linkage and the
// function's type has C language linkage

名称FUNC是用"C“链接声明的,因为它在第一行上写的是extern "C"

名称f2有C++链接,因为这是默认的,第2行没有给出其他链接。

名称f2用于引用具有C链接的函数这一事实并不改变名称的链接。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5763919

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档