惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyberwarzone
Cyberwarzone
Google DeepMind News
Google DeepMind News
宝玉的分享
宝玉的分享
博客园_首页
量子位
博客园 - 司徒正美
罗磊的独立博客
腾讯CDC
IT之家
IT之家
S
Schneier on Security
Hugging Face - Blog
Hugging Face - Blog
L
Lohrmann on Cybersecurity
H
Hacker News: Front Page
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
Know Your Adversary
Know Your Adversary
人人都是产品经理
人人都是产品经理
有赞技术团队
有赞技术团队
大猫的无限游戏
大猫的无限游戏
D
Darknet – Hacking Tools, Hacker News & Cyber Security
AWS News Blog
AWS News Blog
Spread Privacy
Spread Privacy
I
InfoQ
T
Threatpost
Simon Willison's Weblog
Simon Willison's Weblog
云风的 BLOG
云风的 BLOG
L
LINUX DO - 热门话题
A
About on SuperTechFans
Blog — PlanetScale
Blog — PlanetScale
Latest news
Latest news
Forbes - Security
Forbes - Security
Security Latest
Security Latest
NISL@THU
NISL@THU
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
The Hacker News
The Hacker News
M
MIT News - Artificial intelligence
S
SegmentFault 最新的问题
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
B
Blog
A
Arctic Wolf
C
Check Point Blog
G
Google Developers Blog
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
The Cloudflare Blog
L
LINUX DO - 最新话题
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Privacy International News Feed
小众软件
小众软件

博客园 - zim.NET

悼念友人 博客搬家了 函数调用中的黑客技术 3D学习笔记之一句话总结(不断更新中) 混乱你的代码 - zim.NET - 博客园 这么个女孩,你娶吗(转) 被误传了数千年的七句话(精简版_转载) 找工作故事之篇二 找工作故事之开篇 - zim.NET - 博客园 失落的阳光,陈酿的悲伤——许美静 一行命令解决批量重命名 一个空间换时间算法 求最长公共子序列 最小生成树算法讨论 用EditPlus打造你自己的IDE 将PPT内容导出为JPG图片 C/C++ 误区:fflush(stdin) 闲谈成员初始化列表 脑筋急转弯3600题
关于"extern"
zim.NET · 2007-10-01 · via 博客园 - zim.NET

今天是国庆,既然没出去玩,大概得做点有意义的事情吧.决定对C++的一些小知识点来个总结咯.GO ON.

以前只知道extern是声明外部变量的,其它知之甚少,既然知其不知,就要知之.

extern的作用总结起来就两点;

1.使用外部变量或函数

因为C++中文件的链接过程(link)存在着全局变量透明性,(参考[1])即在两个文件中声望两个同名的全局变量,那么在链接的时候就会报错,重复声明.既然在这时不同文件是相对透明的,那么我们要用其它文件的变量或函数就存在可能.而我们又不能再次声明(定义)它,所以引入了extern.

//extern.cpp
extern void print(char *p);
extern int i;
int main(int argc, char* argv[])
{
    
char *p="hello world!";
    print(p);
    
return 0;
}

//print.cpp
#include "stdio.h"
int i;
void print(char *s)
{
    printf(
"The string is %s\n",s);
}

上面在main()调用print()前声明了外部的函数print(), 使用语句extern void print(char *p);还可以省略extern.
同样,看到上面的变量 i 没, 在extern.cpp里用了
extern int i;来引入i. 但这里为什么不能像上面对函数那样省略extern?我的理解是因为extern int i;对变量没有内存分配操作,而若省去则可能导致重复的对i定义.(并非声明),看错误说明大概就是:
print.obj : error LNK2005: "int  i" (?i@@3HA) already defined in extern.obj

2.指示其它语言的函数或变量
比如我们要在C++语言中调用一个C语言的函数.

//test_extern
extern "C" int printf(const char*,);int main()
{
    printf(
"hello , extern\n");return 0;
}

上述的代码包含一个头文件,但仍然是可编译运行的,因为printf()的原型已经有了,而且告诉编译器是外部的一个函数,我想编译器在链接的时候自己乖乖地去匹配了吧.^_^.
注意这里用了extern "C".
当然,我之所以说extern可以指示其它语言的函数或变量,这看你使用的编译器的实现.有的就可以用extern "Ada"或extern "FORTRAN".(参考[2])
如果你试着把extern "C"改为extern的话,你会不幸的链接失败.看如下的错误信息:

Linking
test.obj : error LNK2001: unresolved external symbol 
"int __cdecl printf(char const *,)" (?printf@@YAHPBDZZ)
Debug
/test.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

关键是?printf@@YAHPBDZZ, 别惊奇,如果你知道C语言的编译过程对函数及变量的重命名规则的话,这就是C++编译器对你的printf()函数的重命名.原因主要是为支持C++的新特性吧.
现在存在一个问题,用C语言编译的程序其在.obj中的文件是_printf()命名的. [重命名以下划线开头]而在C++中又是另一种命名方法,如何统一这两种差异,毕竟你要在CPP文件中使用一个以C编译规则得到的函数.就像上面,如果你不写extern "C"的话编译器就找不到你所要的
?printf@@YAHPBDZZ了,于是错误发生.
因此说extern "C" 是链接指示符.

关于extern 就说到这里.如有错误请指正.

参考资料:
[1] keen 专栏:

http://blog.csdn.net/keensword/archive/2005/06/23/401114.aspx
[2] Lippman <C++ Primer>CH7.7   CH8.2