学习过C++的人都知道,extern关键字可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。这里起到的是声明作用范围的用处。另外,extern还可以与”C”连用,作为链接指示。本文就此进行实例说明如下:
一、C++名字修饰(Name Mangling)
首先需要从C++的重载说起,在C++中函数重载指的是几个函数的函数名相同,参数列表不同。那么当生成obj中间文件/目标文件的时候,C++编译器如何区分这几个重载函数呢?可以通过把原函数名与参数信息结合,产生一个独特的内部名字,这种技术叫做名字修饰(Name Mangling)。名字修饰规则没有一个标准,所以不同的编译器的名字修饰规则也不一样。
下面是一组函数,其中f()函数重载了:
int f (void) { return 1; } int f (int) { return 0; } void g (void) { int i = f(), j = f(0); }
f(void)和f(int)是不同的函数,除了函数名相同以外没有任何关系。当生成obj目标文件时,为了区分它们,C++编译器根据参数信息进行了名字修饰:
int __f_v (void) { return 1; } int __f_i (int) { return 0; } void __g_v (void) { int i = __f_v(), j = __f_i(0); }
注意g()也被名字修饰了,虽然没有任何名字冲突。名字修饰应用于C++的任何符号。
二、为什么要使用extern “C”?
C语言中没有名字修饰(Name Mangling),因为C语言不支持函数重载。但是如果C++中含有C代码,在编译时C++编译器对C代码的函数也会进行名字修饰,函数名变了以后,将导致在C运行库中找不到对应函数,发生链接错误。
// 将下面的代码保存为.cpp文件,并用C++编译器编译 int printf(const char *format,...); int main() { printf("GeeksforGeeks"); return 0; }
输出:
/tmp/ccQBO9Im.o:在函数‘main'中: test.cpp:(.text+0xf):对‘printf(char const*, ...)'未定义的引用 collect2: 错误:ld 返回 1
为了防止C++编译器对C代码进行名字修饰,我们将C代码用extern “C”进行链接指定,告诉编译器,在生成中间文件时,不要对这部分代码进行名字修饰,而是生成符合C规则的中间符号名。
extern "C" { int printf(const char *format,...); } int main() { printf("Hello!"); return 0; }
添加了extern “C”链接指示后,上面的代码就能够正常运行了。
附:所有的C风格的头文件(stdio.h, string.h, … 等等)都有在extern “C”下声明,形式如下:
#ifdef __cplusplus extern "C" { #endif /* Declarations of this file */ #ifdef __cplusplus } #endif
我已经开始在win32上使用C。正如我们所知,C结构与类相同,但默认为公共成员等。。。现在我想要的是简单的C结构,它没有默认的构造函数、复制或移动操作或任何其他魔法。因为我想将其存储在文件中,还可以执行memcpy,用作字节数组等。。。所以我想用#ifdef u cplusplus在标题中定义它,如下所示。 但这只能防止函数名称的混乱。但如果在cpp文件中,struct仍然编译为cpp struc
本文向大家介绍实例详解C/C++中extern关键字,包括了实例详解C/C++中extern关键字的使用技巧和注意事项,需要的朋友参考一下 1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。 也就是说extern有两个作用,第一个,当它与"C"一起连用时,如: exter
本文向大家介绍C关键字static、const、extern作用相关面试题,主要包含被问及C关键字static、const、extern作用时的应答技巧和注意事项,需要的朋友参考一下 static和const的作用在描述时主要从类内和类外两个方面去讲: static关键字的作用: (1)函数体内static变量的作用范围为该函数体,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值; (
本文向大家介绍在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?相关面试题,主要包含被问及在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?时的应答技巧和注意事项,需要的朋友参考一下 C++ 语言支持函数重载,C 语言不支持函数重载。函数被C++ 编译后在库中的名字与 C 语言的不同。假设某个函数的原型为:void foo(int x, in
本文向大家介绍ifndef、extern的用法?相关面试题,主要包含被问及ifndef、extern的用法?时的应答技巧和注意事项,需要的朋友参考一下 条件指示符#ifndef 的最主要目的是防止头文件的重复包含和编译。 extern修饰变量的声明。 如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。 这里需要注意的是,被引用的变量v
本文向大家介绍C/C++中*和&的用法详解,包括了C/C++中*和&的用法详解的使用技巧和注意事项,需要的朋友参考一下 C++中&和*的用法一直是非常让人头疼的难点,课本博客上讲这些知识点一般都是分开讲其用法的,没有详细的总结,导致我在这方面的知识结构格外混乱,在网上找到了一篇英文文章简单总结了这两个符号的一些用法,都是一些比较基础的知识,我比较关心的函数指针,指针函数等都没有涉及到,今后有时间把