正好是我们代码中遇到的问题,之前不求甚解,只用g++编译没有错误就不管了,现在要跨平台到windows下就遇到了问题。
全文转载自:http://user.qzone.qq.com/75172588/blog/1248167335

gcc和g++的区别
1、gcc
在编译阶段,把后缀为.c的源文件按照c语法和方式进行编译;把后缀为.cpp的源文件,按照c++语法和方式进行编译。
在链接阶段,不自动和C++程序使用的库链接。所以,.cpp如果有c++的代码,可能会产生链接错误;.c不存在这个问题,因为如果.c如果有c++的代码,编译时就会不通过。
2、g++
在编译阶段,无论是.c还是.cpp,都按照c++的语法和方式进行编译。其实,g++是调用gcc进行编译。
在链接阶段,会自动和C++程序使用的库链接,即便是纯c程序,也会链接这些库。

为什么需要extern “C”?
在c++中,为了支持重载机制,在编译生成的汇编码中,要对函数的名字进行一些处理,加入比如函数的返回类型等等。而在C中,只是简单的函数名字而已,不会加入其他的信息。也就是说,C++和C对产生的函数名字的处理是不一样的。所以,在gcc和g++下编译,会有如下效果:
gcc编译.c文件,因为是按照c方式编译,所以函数名不变;
gcc编译.cpp文件,g++编译.c文件,g++编译.cpp文件,因为是按照c++方式编译,所以函数名加上了附加信息。

在被编译的c++程序中,如果调用了其他的库的函数,则这个函数名也是照加了附加信息的函数名来调的,这样,如果这个库是c方式编译的,那么在库中的函数名是不带附加信息的,这样的调用链接就会失败,因为函数名不对应导致找不到。

在这样的场景下,就需要引入extern “C”。
extern “C”是告诉编译器:这是一个用C写成的库文件,请用C的方式来链接它们。
一般的用法是,比如,现在我们有了一个C库文件,它的头文件是f.h,产生的lib文件是f.lib,那么我们如果要在C++中使用这个库文件,我们需要这样写:

 
1
2
3
4
; html-script: false ]extern "C"
{
#include "f.h"
}

另外,被调函数的实现如果包在extern “C”中,意味着强制按c方式来编译,具体如下:
gcc编译.c文件,会编译不通过,因为c语法中没有extern “C”,实际上在这种情况下根本不需要把函数实现包在extern “C”中,因为这种情况下本来就是按c方式来编译的。因此通常会把代码写成这样:

 
1
2
3
4
5
6
7
8
9
; html-script: false ]#ifdef __cplusplus
extern "C" {
#endif
 
//一段代码
 
#ifdef __cplusplus
}
#endif

__cplusplus宏标志着编译器将会把代码按C还是C++语法来解释,如上所述,如果后缀为.c,并且采用gcc编译器,则该宏就是未定义的,否则,就是已定义的。
gcc编译.cpp文件,g++编译.c文件,g++编译.cpp文件,函数名不变,即采用c的方式。

为什么要把被调函数的实现包在extern “C”里呢?我想是为了使c程序也能调用它,否则就没有什么必要了。

后记:cl编译器的规则与gcc相同。

gcc,g++,extern “C” :一些编译错误的缘由的更多相关文章

  1. gcc/g++ 链接库的编译与链接

    GCC编译步骤 gcc -E t1.c -o t1.i 预处理 gcc -S t1.i -o t1.s 转成汇编语言 gcc -c t1.s -o t1.o 转成机器码 gcc t1.o -o t1. ...

  2. gcc/g++以c++11编译

    方法一: //在程序头加上预定义编译器命令 #pragma GCC diagnostic error "-std=c++11" //通过#pragma 指示 GCC编译器处理错误的 ...

  3. gcc新版本号引起的编译错误(命令运行时的外部库输入位置)

    昨天,遇到一个比較bug的错误,用gcc来编译几个简单的文件出错,编译环境为x86_64的Ubuntu12.04.gcc版本号号例如以下: gcc (Ubuntu/Linaro 4.6.3-1ubun ...

  4. gcc g++支持C++11 标准编译及其区别

    g++ -g -Wall -std=c++11 main.cpp gcc -g -Wall -std=c11 main.cpp 如果不想每次写这个-std=C++11这个选项该怎么办呢? 方法出处:h ...

  5. gcc/g++/make 编译信息带颜色输出

    假设编译一个项目错误警告太多.很不好找,所以很希望输出信息能够带有颜色. 但是 gcc 4.9.0 之前的版本号并不支持,非常多情况下是不能替换编译器的,比方使用交叉编译器, 也能够使用 colorg ...

  6. gcc/g++等编译器 编译原理: 预处理,编译,汇编,链接各步骤详解

    摘自http://blog.csdn.net/elfprincexu/article/details/45043971 gcc/g++等编译器 编译原理: 预处理,编译,汇编,链接各步骤详解 C和C+ ...

  7. gcc/g++ 如何支持c11 / c++11标准编译

    如果用命令 g++ -g -Wall main.cpp  编译以下代码 : /* file : main.cpp */ #include <stdio.h> int main() { in ...

  8. 【转】gcc/g++ 如何支持c11 / c++11标准编译

     如果用命令 g++ -g -Wall main.cpp  编译以下代码 : 1 2 3 4 5 6 7 8 9 10 11 12 /*     file : main.cpp */ #include ...

  9. Linux gcc/g++链接编译顺序详解

    gcc/g++链接时对库的顺序要求 -Ldir Add directory dir to the list of directories to be searched for -l. -llibrar ...

随机推荐

  1. Servlet之过滤器

    Servlet的介绍: Servlet API 中定义了三个接口类来开供开发人员编写 Filter 程序:Filter, FilterChain, FilterConfig Filter 程序是一个实 ...

  2. Linux环境下Websphere重启

    一.Websphere控制台重启 1.更新class文件发布,Websphere自动重启. 2.更新web.xml发布,需要手动更新web.xml或者更新项目. web.config 缓存位置: We ...

  3. Touch ID指纹解锁使用

    Touch ID是iPhone5S后加入的一项新的功能,也就是大家熟知的指纹识别技术.大家用得最多的可能是手机的解屏操作,不用在和以前一样输入手机的四位数密码进行验证.一方面不用担心密码被别人看到,另 ...

  4. ios开发入门篇(三):UITableView简介

    最近做项目又开始用到了uitableview,温习之余,在这里把uitableview的用法分享一下,有不对的地方欢迎大家提出来. 废话不多说,先创建一个工程,由于Xcode6,去除了创建工程时的空项 ...

  5. template_1

    0: 模板是一些为多种类型而编写的函数和类,而且这些类型都没有指定.当使用模板的时候,只需要把所希望的类型作为一个(显示或隐示的)实参传递给模板.模板是语言本身所具有的特效,她完全支持类型检查和作用域 ...

  6. Memcached的安装(Linux)、操作、命令

    最近在整理有关分布式缓存的服务器,做了一下老牌nosql服务器memcached的学习总结.文中所述的所有安装均是在联网的情况下进行的. 序: 什么是memcached: Free & ope ...

  7. MongoDB的安全性

    上篇文章介绍Mongo启动了,一般数据库启动,下面的操作就是登录数据库了,之前测试数据库是否正常安装的时候也登录过数据库,现在回想一下,好像连用户名和密码都没有输入,找几篇帖子来探究下Mongodb的 ...

  8. 3.12php

    这是我的第一个博客  纪念一下  反正都是自己看 第一个问题 出现错误 当图片超过1M时就可能出现以下错误  当然这个也跟你php.ini设置有关 如果你php设置里 memory_limit 16M ...

  9. jdbc之分页查询

    分页查询作为一项十分重要的数据库查询技术,在很多web项目中都会要用到,当然移动开发中也是会涉及的. 一.分页查询的sql语句: ps:为了方便阐述,下面统一使用student表作为查询的表:colN ...

  10. Spark Streaming揭秘 Day32 WAL框架及实现

    Spark Streaming揭秘 Day32 WAL框架及实现 今天会聚焦于SparkStreaming中非常重要的数据安全机制WAL(预写日志). 设计要点 从本质点说,WAL框架是一个存储系统, ...