详解C/C++ 编译 g++ gcc 的区别
我们在编译c/c++代码的时候,有人用gcc,有人用g++,于是各种说法都来了,譬如c代码用gcc,而c++代码用g++,
或者说编译用gcc,链 接用g++,一时也不知哪个说法正确,如果再遇上个extern "C",分歧就更多了,这里我想
作个了结,毕竟知识的目的是令人更清醒,而不是更糊涂。
误区一:gcc只能编译c代码,g++只能编译c++代码
两者都可以,但是请注意:
.后缀为.c的,gcc把它当作是C程序,而g++当作是c++程序;后缀为.cpp的,两者都会认为是c++程序,注意,虽然
c++是c的超集,但是两者对语法的要求是有区别的,例如:
#include <stdio.h>
int main(int argc, char* argv[]) {
if(argv == ) return;
printString(argv);
return;
}
int printString(char* string) {
sprintf(string, "This is a test.\n");
}
如果按照C的语法规则,OK,没问题,但是,一旦把后缀改为cpp,立刻报三个错:“printString未定义”;
“cannot convert `char**' to `char*”;
”return-statement with no value“;
分别对应前面红色标注的部分。可见C++的语法规则更加严谨一些。
.编译阶段,g++会调用gcc,对于c++代码,两者是等价的,但是因为gcc命令不能自动和C++程序使用的库联接,
所以通常用g++来完成链接,为了统一起见,干脆编译/链接统统用g++了,这就给人一种错觉,好像cpp程序只能用
g++似的。 误区二:gcc不会定义__cplusplus宏,而g++会
实际上,这个宏只是标志着编译器将会把代码按C还是C++语法来解释,如上所述,如果后缀为.c,并且采用gcc编译
器,则该宏就是未定义的,否则,就是已定义。 误区三:编译只能用gcc,链接只能用g++
严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用gcc/g++,而链接可以用g++或者
gcc -lstdc++。因为gcc命令不能自动和C++程序使用的库联接,所以通常使用g++来完成联接。但在编译阶段,
g++会自动调用gcc,二者等价。 误区四:extern "C"与gcc/g++有关系
实际上并无关系,无论是gcc还是g++,用extern "c"时,都是以C的命名方式来为symbol命名,否则,都以c++方式
命名。试验如下:
me.h:
extern "C" void CppPrintf(void); me.cpp:
#include <iostream>
#include "me.h"
using namespace std;
void CppPrintf(void)
{
cout << "Hello\n";
} test.cpp:
#include <stdlib.h>
#include <stdio.h>
#include "me.h"
int main(void)
{
CppPrintf();
return ;
} . 先给me.h加上extern "C",看用gcc和g++命名有什么不同
[root@root G++]# g++ -S me.cpp
[root@root G++]# less me.s
.globl _Z9CppPrintfv //注意此函数的命名
.type CppPrintf, @function
[root@root GCC]# gcc -S me.cpp
[root@root GCC]# less me.s
.globl _Z9CppPrintfv //注意此函数的命名
.type CppPrintf, @function
完全相同! . 去掉me.h中extern "C",看用gcc和g++命名有什么不同
[root@root GCC]# gcc -S me.cpp
[root@root GCC]# less me.s
.globl _Z9CppPrintfv //注意此函数的命名
.type _Z9CppPrintfv, @function
[root@root G++]# g++ -S me.cpp
[root@root G++]# less me.s
.globl _Z9CppPrintfv //注意此函数的命名
.type _Z9CppPrintfv, @function
完全相同!
【结论】完全相同,可见extern "C"与采用gcc/g++并无关系,以上的试验还间接的印证了前面的说法:在编译阶段,
g++是调用gcc的
在Linux下一会看到cc,另一会又看到gcc,感觉又点混乱的样子。它们是同一个东西么,有啥区别呢
一分为二地看:
首先,如果讨论范围在Unix和Linux之间,那么cc和gcc不是同一个东西。cc来自于Unix的c语言编译器,
是 c compiler 的缩写。gcc来自Linux世界,是GNU compiler collection 的缩写,注意这是一个编译
器集合,不仅仅是c或c++。 其次, 如果讨论范围仅限于Linux,我们可以认为它们是一样的,在Linux下调用cc时,其实际上并不指
向unix的cc编译器,而是指向了gcc,也就是说cc是gcc的一个链接(快捷方式),看看下面的终端输出就明白了:
zhouyinhui@zhouyinhui-laptop:/etc/alternatives$ which cc
/usr/bin/cc
zhouyinhui@zhouyinhui-laptop:/etc/alternatives$ ls -al /usr/bin/cc
lrwxrwxrwx 1 root root 20 2010-01-20 23:56 /usr/bin/cc -> /etc/alternatives/cc
zhouyinhui@zhouyinhui-laptop:/etc/alternatives$ ls -al /etc/alternatives/cc
lrwxrwxrwx 1 root root 12 2010-01-20 23:56 /etc/alternatives/cc -> /usr/bin/gcc 为什么会这样,很简单,为了兼容性:
cc是Unix下的,是收费的,可不向Linux那样可以那来随便用,所以Linux下是没有cc的
然后,问题来了,如果我的c/c++项目是在Unix下编写的,在写makefile文件时自然地用了cc,当将其放到Linux
下这无法make了,必须将其中的cc全部修改成gcc。这太麻烦了哈,所以,Linux这想了这么一个方便的解决方案:
不修改makefile,继续使用cc,这个cc是个“冒牌货”,它实际指向gcc。
详解C/C++ 编译 g++ gcc 的区别的更多相关文章
- HTTP详解(3)-http1.0 和http1.1 区别
HTTP详解(3)-http1.0 和http1.1 区别 分类: 网络知识2013-03-17 16:51 1685人阅读 评论(0) 收藏 举报 目录(?)[+] 翻了下HTTP1.1的协 ...
- 详解 $_SERVER 函数中QUERY_STRING和REQUEST_URI区别
详解 $_SERVER 函数中QUERY_STRING和REQUEST_URI区别 http://blog.sina.com.cn/s/blog_686999de0100jgda.html 实例: ...
- python爬虫---详解爬虫分类,HTTP和HTTPS的区别,证书加密,反爬机制和反反爬策略,requests模块的使用,常见的问题
python爬虫---详解爬虫分类,HTTP和HTTPS的区别,证书加密,反爬机制和反反爬策略,requests模块的使用,常见的问题 一丶爬虫概述 通过编写程序'模拟浏览器'上网,然后通 ...
- 正则表达式中模式修正符作用详解(i、g、m、s、x、e)
下面的转:http://www.cnblogs.com/shunyao8210/archive/2008/11/13/1332591.html 总结1:附件参数g的用法 表达式加上参数g之后,表明可以 ...
- [转] 详解http和https的作用与区别
PS: https就是http和TCP之间有一层SSL层,这一层的实际作用是防止钓鱼和加密.防止钓鱼通过网站的证书,网站必须有CA证书,证书类似于一个解密的签名.另外是加密,加密需要一个密钥交换算法, ...
- g++ gcc 的区别
我们在编译c/c++代码的时候,有人用gcc,有人用g++,于是各种说法都来了,譬如c代码用gcc,而c++代码用g++,或者说编译用gcc,链 接用g++,一时也不知哪个说法正确,如果再遇上个ext ...
- 详解http和https的作用与区别
PS: https就是http和TCP之间有一层SSL层,这一层的实际作用是防止钓鱼和加密.防止钓鱼通过网站的证书,网站必须有CA证书,证书类似于一个解密的签名.另外是加密,加密需要一个密钥交换算法, ...
- 详解多线程MT和多线程MD的区别
这段时间司在招实习生,而不管是远程的电话面试或者是实际现场面试中领导都喜欢问你这个问题,但是可惜的是能很好答上来的人很少.后来发现不管是应届的实习生,甚至有些实际参加工作几年的人也未必真的了解这个问题 ...
- css学习--inline-block详解及dispaly:inline inline-block block 三者区别精要概括
*知识储备: 内联元素:是不可以控制宽和高.margin等:并且在同一行显示,不换行. 块级元素:是可以控制宽和高.margin等,并且会换行. 1.inline-block 详解 (1)一句话就是在 ...
随机推荐
- robotframe使用之时间控件
robotframe使用之时间控件 正常的页面,时间控件会写在一个iframe里面,所以robotframework找不到对的ID或者xpath等. 要解决这个问题必选先显示iframe. 使用关键字 ...
- Robot Framework ---Selenium API
一.浏览器驱动 通过不同的浏览器执行脚本. Open Browser Htpp://www.xxx.com chrome 浏览器对应的关键字: firefox FireFox ff internete ...
- Pyqt4 360界面风格皮肤实现
前言 最近用Pyqt做了软件界面,始终觉得windows风格不太好看,虽然数字公司的行为有争议,但是也不影响我欣赏360卫士的界面风格. 声明 首先声明,此项工作并非原创,而是基于这位zhuyeqin ...
- Spring IOC源码分析之-刷新前的准备工作
目录 ClassPathXmlApplicationContext的注册方式 加载父子容器 配置路径解析 容器刷新 刷新容器之刷新预处理 ClassPathXmlApplicationContext的 ...
- GIT简单使用——多人协作篇
多人协作的工作模式通常是这样:1.首先,可以试图用git push origin <branch-name>推送自己的修改:2.如果推送失败,则因为远程分支比你的本地更新,需要先用git ...
- jquery判断复选框是否被选中
$("#isUse").click(function(){ if($(this).is(':checked')){ $(this).attr('checked','checked' ...
- linux 跟踪工具
strace工具,进程诊断.排错.跟踪系统调用和信号量 每行输出都是一个系统调用,包括函数和返回值. strace是Linux环境下的一款程序调试工具,用来监察一个应用程序所使用的系统调用及它所接收的 ...
- Nginx负载均衡简易配置
多台Web服务器水平扩展,进行负载均衡对外服务,是一种很常见的方案. 常用方法用DNS轮询,LVS. DNS轮询虽然有配置简单的有点,但无法实现健康检查,DNS修改需要较长时间失效,对于无域名的内部服 ...
- PowerBuilder -- Len(), LenA() 与 String, Blob
使用的是Powerbuilder12.5与Powerbuild9 不太一样 函数 String Blob Len() 返回字符数 返回字符数对应的字节数 LenA() 返回字节数 返回字符数对应的字节 ...
- 平滑处理 - cvSmooth() 函数实现
前言 平滑是图像处理中很重要的操作,其主要用途是降噪.Open CV 提供了 5 种不同的平滑方法:简单模糊,简单无缩放变换的模糊,中值模糊,高斯模糊和双边滤波,它们都通过函数 cvSmooth 实现 ...