c++中的external function啥意思

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++中的external function啥意思相关的知识,希望对你有一定的参考价值。

在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。

1. extern修饰变量的声明。举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说a.c要引用到v,不只是取决于在a.c中声明extern int v,还取决于变量v本身是能够被引用到的。这涉及到c语言的另外一个话题--变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全局变量。还有很重要的一点是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函数fun定义的开头处声明extern int v,然后就可以引用到变量v了,只不过这样只能在函数fun作用域中引用v罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑。好像extern声明只能用于文件作用域似的。

2. extern修饰函数声明。从本质上来讲,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int fun(int mu),那么就可以在a.c中声明extern int fun(int mu),然后就能使用fun来做任何事情。就像变量的声明一样,extern int fun(int mu)可以放在a.c中任何地方,而不一定非要放在a.c的文件作用域的范围中。对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。使用extern和包含头文件来引用函数有什么区别呢?extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。这大概是KISS原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。

extern "C"的含义

extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。
被extern "C"限定的函数或变量是extern类型的;
被extern "C"修饰的变量和函数是按照C语言方式编译和链接的

首先看看C++中对类似C的函数是怎样编译的。
作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:
void foo( int x, int y );
该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。
_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。 例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。
同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

举例说明
(1)未加extern "C"声明时的连接方式
假设在C++中,模块A的头文件如下:
// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif
//在模块B中引用该函数:
// 模块B实现文件 moduleB.cpp
#include "moduleA.h"
foo(2,3);

实际上,在连接阶段,链接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!

(2)加extern "C"声明后的编译和链接方式
加extern "C"声明后,模块A的头文件变为:
// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y );
#endif

在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:

<1>A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;

<2>链接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。

如果在模块A中函数声明了foo为extern "C"类型,而模块B中包含的是extern int foo(int x, int y),则模块B找不到模块A中的函数;反之亦然。

extern “C”这个声明的真实目的是为了实现C++与C及其它语言的混合编程。
参考技术A 在C++中external function是外部函数的意思,而外部函数有两种理解.(1)库函数是C语言的内部函数或自带函数,外部函数即程序员自定函数.
(2)凡加写了extern 的函数是外部函数.本回答被提问者采纳

Javascript 中的 !function 是啥意思? [复制]

【中文标题】Javascript 中的 !function 是啥意思? [复制]【英文标题】:what does !function in Javascript mean? [duplicate]Javascript 中的 !function 是什么意思? [复制] 【发布时间】:2012-03-05 06:06:22 【问题描述】:

很抱歉发布此内容,但 !function 无法通过 Google 搜索,而且我在我的 JavaScript 代码中没有找到它。

以下是 Twitter 的使用方式:

<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://google.com" data-text="Google says">Tweet</a>
<script>!function(d,s,id)var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id))js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);(document,"script","twitter-wjs");</script>

来自https://twitter.com/about/resources/buttons#

【问题讨论】:

【参考方案1】:

他们否定结果,而不是函数本身:

!function( x ) return x ( true );
!true
false

实际上,它是一种略微压缩的形式:

(function()())

因为它需要少 1 个字符。需要它的原因是您不能直接调用函数声明,例如这是无效的:

function()()

但在开头添加 ! 会将其变为函数 expression 并使其工作。

【讨论】:

有趣的技术... “否定结果”具有误导性,@Twisol 的回答更准确 @ŠimeVidas -- 我感觉这是生成的代码,用于寻找自调用函数模式,因为它确实节省了 1 个字符 :) @Jonz -- 是的,它会在扔掉它之前对其进行评估,而不是像一个昂贵的操作。它还可以防止代码中的错误基本上计算为:(function())()(function())()——中间缺少;意味着第二个函数被传递给第一个函数的结果。通常不需要的行为会导致错误或非常奇怪的行为。 ! 或任何二进制操作都可以防止这种情况发生 @downeyt ! 没有两个含义。当 JS 运行时看到 ! 时,它知道它只能表示(因为 ! 只有一个含义)逻辑否定,因此,JS 运行时明白你只能否定一个表达式,而不是一个语句,所以指令的其余部分被视为这样。在这种用法中,表达式的结果无关紧要并被丢弃。没有双重含义。【参考方案2】:

它是self-invoking anonymous function的简写或替代:

(function()
  // code
)();

可以写成:

!function()
  // code
();

您也可以使用+ 代替!

如果你只是这样做:

function()
  // code
();

这会产生问题,这就是为什么你需要在它之前添加!,这会将函数声明变成函数表达式

Quoting docs, section 12.4:

ExpressionStatement 不能以 function 关键字开头,因为 这可能会使 FunctionDeclaration 变得模棱两可。

为了更好地理解这个概念,您应该查看:

Function Declarations vs. Function Expressions

【讨论】:

有趣。自调用匿名函数何时有用?和简单的执行里面的语句有什么区别? @netvope:见***.com/questions/592396/… 我明白了。谢谢。如果 Javascript 支持仅使用大括号(如在 C++ 中)进行作用域,那就太好了 @netvope ECMAScript 6(又名 ES 2015)确实支持带有 letconst 声明的块级范围。【参考方案3】:

它通常用于解决 JavaScript 语法中的一个怪癖。这给出了一个语法错误:

function() 
();

它被读作函数声明(如function foo () ),而不是函数表达式。所以添加!在它之前,或者用括号括起来,强制解析器理解它是一个表达式。

【讨论】:

这不是语法的怪癖。这只是语法。

以上是关于c++中的external function啥意思的主要内容,如果未能解决你的问题,请参考以下文章

c语言中的extern是啥,有啥作用啊?

c++说miss function header 是啥意思

external-libraries是啥意思

external是啥意思?怎么读?

_external=True 在 flask_mail 中是啥意思?

[=] 在 C++ 中是啥意思?