参考文章:http://blog.csdn.net/sruru/article/details/7951019

chapter1、如何混合编译C语言和C++

实际开发过程中,C++中会调用C与语言编写的代码,我在网络上面找到一篇写得很好的文章

http://blog.csdn.net/keensword/article/details/401114

方法一、全局函数和变量在devVar.c文件中实现,在extern.cpp文件中使用extern关键字声明在devVar.c文件中定义的函数和变量。

devVar.c文件的代码如下所示:

  1. #include <stdio.h>
  2. int i = 1;
  3. void func()
  4. {
  5. printf("%d",i++);
  6. }

extern.cpp文件中代码如下所示:

  1. #include "stdafx.h"
  2. #include <stdio.h>
  3. #include <iostream>
  4. using namespace std;
  5. //#include "devVar.h"
  6. //extern int i;
  7. //extern void func();
  8. extern "C"
  9. {
  10. extern int i;
  11. extern void func();
  12. //#include "devVar.h"
  13. }
  14. int main(void)
  15. {
  16. for (int x = 0;x < 10; x++)
  17. {
  18. func();
  19. }
  20. }

所以在C++文件中编译C文件需要使用extern "C"关键字,声明语法如下所示

extern "C"

{

采用C语言实现的内容

}

方法二、

在devVar.h文件中实现C代码(即devVar.h作为C语言头文件),在.cpp文件中包含C语言头文件。

devVar.h头文件内容为:

  1. #include <stdio.h>
  2. int i = 1;
  3. void func()
  4. {
  5. printf("%d",i++);
  6. }

extern.cpp文件内容如下所示

  1. #include "stdafx.h"
  2. #include <stdio.h>
  3. #include <iostream>
  4. using namespace std;
  5. //#include "devVar.h"
  6. //extern int i;
  7. //extern void func();
  8. extern "C"
  9. {
  10. //extern int i;
  11. //extern void func();
  12. #include "devVar.h"
  13. }
  14. int main(void)
  15. {
  16. for (int x = 0;x < 10; x++)
  17. {
  18. func();
  19. }
  20. }

其中,包含C语言头文件的方式为:

  1. extern "C"
  2. {
  3. //extern int i;
  4. //extern void func();
  5. #include "devVar.h"
  6. }

写到这里,楼主又产生了一个疑问,上面的例子讲的是C++调用C实现的代码,那如果是C调用C++编写的代码呢?

楼主作了如下改动:

devVar.cpp代码为:

  1. #include <stdio.h>
  2. int i = 1;
  3. void func()
  4. {
  5. printf("%d",i++);
  6. }

extern.c文件代码为

  1. #include <stdio.h>
  2. extern int i;
  3. extern void func();
  4. int main(void)
  5. {
  6. int x = 0;
  7. for (;x < 10; x++)
  8. {
  9. func();
  10. }
  11. }

单独编译每个文件都通过,链接声称可执行文件的时候报错:

1>extern.obj : error LNK2019: unresolved external symbol _func referenced in function _main,说明.c文件中extern void func(),按照C编译的规则,得到函数_func,而devVar.cpp文件采用C++编译方式,得到的函数为XX·!_func(具体楼主也不知道哈),这样链接的时候函数自然找不到,那怎么解决呢?

需要在devVar.cpp中,明确调用extern "C"关键字,声明cpp文件中有关代码,需要按照C的方式来生成,修改devVar.cpp文件如下所示:

  1. #include <stdio.h>
  2. int i = 1;
  3. extern "C" void func()
  4. {
  5. printf("%d",i++);
  6. }

此时,除了需要使用extern "C"声明编译的时候采用C方式编译外,.cpp文件中的代码可以按照C++方式编写,例如

devVar.cpp按照下面方式写,也是正确的。

  1. #include "stdafx.h"
  2. #include <iostream>
  3. using namespace std;
  4. int i = 1;
  5. extern "C" void func()
  6. {
  7. cout << "i = " << i++ << endl;

chapter 2 . extern关键字的作用

extern是一个关键字,它告诉编译器存在着一个变量或者一个函数,如果在当前编译语句的前面中没有找到相应的变量或者函数,也会在当前文件的后面或者其它文件中定义,来看下面的例子。

  1. // extern.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include <iostream>
  5. using namespace std;
  6. extern int i;
  7. extern void func();
  8. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain
  9. {
  10. i = 0;
  11. func();
  12. return 0;
  13. }
  14. int i;
  15. void func()
  16. {
  17. i++;
  18. cout << "i = " << i << endl;
  19. }

上面代码中变量i和函数func在文件末尾定义,所以变量需要使用extern关键字告诉编译器,变量在别的地方定义。extern int i我原来以为extern i就可以,结果编译器报错,仔细想下确实应该,否则编译器不知道i是什么类型的数据,又怎么能判断i = 0是否是一个正确的赋值语句呢?

那么定义在其他文件中的函数和变量,如何通过extern关键字调用呢?

首先,定义在其它文件中的函数和变量,可以使用两种方法调用:

一、使用头文件调用,这时候,函数和变量必须在头文件中定义和声明。

二、使用extern关键字调用,这时候函数和变量在.cpp或者.c文件中定义和声明。

看下面两个例子:

devVar.cpp函数中定义:

  1. #include "stdafx.h"
  2. int i;

extern.cpp中

  1. // extern.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include <iostream>
  5. using namespace std;
  6. extern int i;
  7. extern void func();
  8. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain
  9. {
  10. i = 0;
  11. func();
  12. return 0;
  13. }
  14. void func()
  15. {
  16. i++;
  17. cout << "i = " << i << endl;
  18. }

编译工程,程序输出:i = 1,这里使用extern关键字声明在其它cpp文件中定义的变量和函数。

#include <filensme> --- 将filename文件中的内容插入到新的文件中。

deVar.h文件中代码为

  1. #include <stdio.h>
  2. int i = 1;
  3. void func()
  4. {
  5. printf("%d",i++);
  6. }

函数func修改全局变量i的值并输出。

extern.cpp文件内容为:

  1. #include "stdafx.h"
  2. #include <stdio.h>
  3. #include <iostream>
  4. using namespace std;
  5. #include "devVar.h"
  6. //extern int i;
  7. //extern void func();
  8. int main(void)
  9. {
  10. for (int x = 0;x < 10; x++)
  11. {
  12. func();
  13. }
  14. }

程序输出1,2,3,4,5,6,7,8,9,10,这里#include <filname.h> 包含定义在其它头文件中的函数和变量,在来看一个例子。

  1. // extern.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include <iostream>
  5. using namespace std;
  6. extern int i;
  7. extern int  func(int);//这里extern必需的,函数定义在其它cpp文件中
  1. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain
  2. {
  3. i = 100;
  4. func(i);
  5. return 0;
  6. }

devVar.cpp文件中内容为:

  1. #include "stdafx.h"
  2. #include <iostream>
  3. using namespace std;
  4. int i;
  5. int func(int a)
  6. {
  7. i = a;
  8. cout << "i = " << i << endl;
  9. return 0;
  10. }

这样,同样是输出了i= 100。

能够使用extern引用其它cpp文件中定义的函数说明了一个问题:

如果一个工程现编译cpp文件,在把多个目标文件链接成为可执行文件,而两个或多个文件中,定义了相同的全局变量,那么,程序编译的时候不会报错,因为编译器单独编译每个文件,在链接可执行文件的时候,由于多个目标文件中含有相同的全局变量,而生成可执行文件的时候,任何文件中定义的全局变量对其它目标文件都是可见的,此时由于变量定义冲突而发生错误。看下面的代码:

  1. // extern.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include <iostream>
  5. using namespace std;
  6. int i;
  7. extern int  func(int);//这里extern是必须的函数定义在别的cpp文件中
  8. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain
  9. {
  10. i = 100;
  11. func(i);
  12. return 0;
  13. }

devVar.cpp文件中,内容为:

  1. #include "stdafx.h"
  2. #include <iostream>
  3. using namespace std;
  4. int i;
  5. int func(int a)
  6. {
  7. i = a;
  8. cout << "i = " << i << endl;
  9. return 0;
  10. }

单独compile任何一个cpp文件都是对的,但是 编译工程,生成可执行文件的时候报错:

1>LINK : D:\vctest\extern\Debug\extern.exe not found or not built by the last incremental link; performing full link
1>devVar.obj : error LNK2005: "int i" (?i@@3HA) already defined in extern.obj
1>D:\vctest\extern\Debug\extern.exe : fatal error LNK1169: one or more multiply defined symbols found

原因是:两个.cpp文件中都定义了全局变量i,变量重复定义了。

PS:定义在.h文件中的函数和变量不能使用extern变量声明,原因是#include <filename>在预编译的时候将.h文件中的内容插入了cpp文件中,因此编译器找得到在其它.h文件中定义的变量或者函数。编译的时候,只编译cpp文件的内容,.h文件时不参与编译,如果使用extern声明在.h文件中定义的变量或者函数,那么声明为extern的变量和函数在其它.cpp文件中找不到,因此程序编译的时候就发生了错误。

 

C++中extern关键字使用(转)的更多相关文章

  1. 【转载】C/C++中extern关键字详解

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  2. C++中extern关键字用法小结

    总结C++中关于extern关键字的用法. 1.变量的生明和定义中 C++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译.为了将程序分为许多文件,则需要在文件中共享代码 ...

  3. C/C++中extern关键字解析

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  4. C/C++中extern关键字详解

    转自:http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777431.html 1 基本解释:extern可以置于变量或者函数前,以标示变 ...

  5. C/C++中extern关键字详解(转)

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  6. [UE4]C++中extern关键字浅谈

    变量声明和变量是有区别的 extern int i; //只是声明i而非定义i int j; //声明而且还定义了j 任何一个显式初始化的声明都将成为定义,而不管有没有extern,extern语句一 ...

  7. iOS 中 const static extern 关键字总结

    在看一些高手所写的代码时,总是可以看到我们小白平常不用的关键字,一次,两次,三次,不能总是不明不白,现在总结一下日常开发中常用的关键字的作用: 关键字const/static/extern的释义和用法 ...

  8. C语言中的 extern 关键字

    今天在 BLE 中看到很多 extern 关键字,现在总结一下: extern 关键字主要用于在一个c文件中要用到另一个c文件中的变量或者函数. example: #extern_base.c ; # ...

  9. 【转载】理解C语言中的关键字extern

    原文:理解C语言中的关键字extern 最近写了一段C程序,编译时出现变量重复定义的错误,自己查看没发现错误.使用Google发现,自己对extern理解不透彻,我搜到了这篇文章,写得不错.我拙劣的翻 ...

随机推荐

  1. Node.js权威指南 (10) - Node.js中的错误处理与断言处理

    10.1 使用domain模块处理错误 / 272 10.1.1 domain模块概述 / 272 10.1.2 创建并使用Domain对象 / 274 10.1.3 隐式绑定与显式绑定 / 276 ...

  2. LINUX系统中动态链接库的创建与使用

    大家都知道,在WINDOWS系统中有很多的动态链接库(以.DLL为后缀的文件,DLL即Dynamic Link Library).这种动态链接库,和静态函数库不同,它里面的函数并不是执行程序本身的一部 ...

  3. (转载)shell中用date命令获取昨天、明天或者多天前的日期

    (转载)http://blog.sina.com.cn/s/blog_3e4774e30100p0yv.html 使用date命令获取日期很方便,最近需要获取当前日期的下一天日期在linux应该如何获 ...

  4. HDOJ/HDU 2537 8球胜负(水题.简单的判断)

    Problem Description 8球是一种台球竞赛的规则.台面上有7个红球.7个黄球以及一个黑球,当然还有一个白球.对于本题,我们使用如下的简化规则:红.黄两名选手轮流用白球击打各自颜色的球, ...

  5. cocos2d的ARC开启

    ARC,官方解释是Automatic Reference Counting,是Apple公司从iOS5开始为开发者新添加的一个功能. 相信很多写移动开发,可能不只是移动开发的人都深有体会,创建一个对象 ...

  6. [JIT_APP]Android SQLite简介

    SQLite介绍 SQLite是一个非常流行的嵌入式数据库,它支持SQL语言,并且只利用很少的内存就有很好的性能.此外它还是开源的,任何人都可以使用它.许多开源项目(Mozilla, PHP, Pyt ...

  7. 一键清除cvs/svn 目录

    步骤一.编写注册表脚本      新建一个文本文件,把下面的代码COPY进去,保存为delSVNorCVS.reg(可直接从本文附件中下载) Windows Registry Editor Versi ...

  8. IOS学习之路十五(UIView 添加背景图片以及加边框)

    怎样给UIview添加背景图片呢很简单,就是先给view添加一个subview,然后设为背景图片: 效果图如下: 很简单直接上代码: //设置内容 self.myTopView.backgroundC ...

  9. 002-python书写规范--消去提示波浪线

    强迫症患者面对PyCharm的波浪线是很难受的,针对如下代码去除PyCharm中的波浪线: # _*_coding:utf-8_*_ # /usr/bin/env python3 A_user = & ...

  10. Codeforces Round #387(div 2)

    A =w= B VOV C QoQ D 题意:贝尔兰冬天很冷,那么司机要换上冬天专用轮胎才能开车.假设冬天一共有n天,有一套冬天专用轮胎,仅能使用k天,这套轮胎不管什么温度都能用,而夏天用的轮胎只能在 ...