我们知道,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

C++学习之extern "C"的更多相关文章

  1. NSNotification Name 最佳写法

    本文主要借探讨NSNotificationName的最佳写法的机会,学习下extern, static, const, #define 和常量指针与指针常量等的特性和用法. 1.NSNotificat ...

  2. C语言 extern学习2 分析

    上一篇文章中,通过头文件声明,而调用有一个特别大的漏洞: 为什么编译器可以链接过来呢,因为默认是extern修饰的,这种类似全局作用域的功能使其可以被调用 继续加强学习: 这一次有两对C文件: fir ...

  3. 在 C# CLR 中学习 C++ 之了解 extern

    一:背景 在 CLR 源码中有很多的 extern 和 extern "C" 这样的关键词,比如下面这些代码: extern size_t gc_global_mechanisms ...

  4. C语言学习及应用笔记之六:C语言extern关键字及其使用

    在C语言中,修饰符extern用在变量或者函数的声明前,用来以标识变量或者函数的定义在别的文件中,提示编译器遇到此变量或者函数时,在其它文件中寻找其定义.extern关键字的用法有几种,我们下面对其进 ...

  5. C++ Primer 学习笔记与思考_3 ---头文件那些事儿(extern)

    (一)extern在头文件里的使用方法 由于头文件包括在多个源文件里.而且变量的定义仅仅能出现一次,所以在头文件里. 仅仅能够声明不能够出现定义. 我们能够在头文件里用extern声明全局变量,这样在 ...

  6. [C语言学习笔记二] extern 函数的用法

    extern 用来定义一个或多个变量.其后跟数据类型名和初始值.例如: extern int a =10 它与 int,long long int,double,char的本质区别,在于 extern ...

  7. C语言 extern学习1

    没有头文件时,通过本文件内的函数声明来确定定义域,实现功能: //单文件测试 #include <stdio.h> /* 经测试,C语言环境下子函数默认是void型:所以可省略不写 为严谨 ...

  8. [机器学习] 深度学习之caffe1——软件配置与测试

    caffe的编译配置真的是很让人头疼啊,不知道试过多少次了~~~ 重装系统了七八次,搞得linux的一些常用命令倒是很熟悉了~~~ 我有洁癖~~~某一个点上出了错,我一定要把它搞好了,再重新来一次,我 ...

  9. 【NopCommerce源码架构学习-一】--初识高性能的开源商城系统cms

    很多人都说通过阅读.学习大神们高质量的代码是提高自己技术能力最快的方式之一.我觉得通过阅读NopCommerce的源码,可以从中学习很多企业系统.软件开发的规范和一些新的技术.技巧,可以快速地提高我们 ...

随机推荐

  1. LN : leetcode 515 Find Largest Value in Each Tree Row

    lc 515 Find Largest Value in Each Tree Row 515 Find Largest Value in Each Tree Row You need to find ...

  2. LR接口测试---webservices

    //================================================================================== /* //事务开始 lr_st ...

  3. Reuse a SSL socket

    It's possible to reuse a SSL socket after proper cleanup. See SSL Socket free and shutdown on stacko ...

  4. Assembly之instruction之JC

    JC Jump if carry setJHS  Jump if higher or same Syntax JC label JHS label Operation If C = 1: PC + 2 ...

  5. 【sqli-labs】 对于less34 less36的宽字节注入的一点深入

    1.AddSlashes() 首先来观察一下是如何通过构造吃掉转义字符的 先将less 34的网页编码换成gbk 加上一些输出 echo "Before addslashes(): &quo ...

  6. 【sqli-labs】 less61 GET -Challenge -Double Query -5 queries allowed -Variation4 (GET型 挑战 双查询 只允许5次查询 变化4)

    http://192.168.136.128/sqli-labs-master/Less-61/?id=1' 单引号双括号闭合 192.168.136.128/sqli-labs-master/Les ...

  7. POJ_1611_The Suspect

    The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 25149   Accepted: 12329 De ...

  8. PHP 之QQ第三方登录

    一.下载QQ SDK 下载地址:http://wiki.open.qq.com/wiki/mobile/SDK 二.配置SDK 三.具体代码 login.html <!DOCTYPE html& ...

  9. ThinkPHP---thinkphp文件加载

    [一]文件加载在ThinkPHP里提供了三种方式 实际开发里,文件加载方式一般以第一种为主(通过函数库形式自动加载,此时我们仅仅需要定义文件和函数) (1)函数库形式加载 函数库分3种级别,系统函数库 ...

  10. [转]Js获取当前日期时间及其它操作

    转载自:http://www.cnblogs.com/carekee/articles/1678041.html Js获取当前日期时间及其它操作 var myDate = new Date();myD ...