gcc与g++的区别

2023-05-16

一、编译的四个阶段
预处理:编译处理宏定义等宏命令(eg:#define)——生成后缀为“.i”的文件   
编译:将预处理后的文件转换成汇编语言——生成后缀为“.s”的文件   
汇编:由汇编生成的文件翻译为二进制目标文件——生成后缀为“.o”的文件   
连接:多个目标文件(二进制)结合库函数等综合成的能直接独立执行的执行文件——生成后缀为“.out”的文件
在我们理解了上述四个流程后,我们在关注gcc和g++在流程上的区别。
gcc无法进行库文件的连接,即无法编译完成步骤4;而g++则能完整编译出可执行文件。(实质上,g++从步骤1-步骤3均是调用gcc完成,步骤4连接则由自己完成)

二、gcc 与g++的区别
首先说明:gcc 和 GCC 是两个不同的东西
GCC:GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、JAV、Fortran、Pascal、Object-C、Ada等语言。
gcc是GCC中的GUN C Compiler(C 编译器)
g++是GCC中的GUN C++ Compiler(C++编译器)

误区一:gcc只能编译C代码,g++只能编译c++代码。
事实上,二者都可以编译c或cpp文件。
gcc和g++的主要区别

对于 .c和.cpp文件,gcc分别当做c和cpp文件编译(cpp的语法规则比c的更强一些)
对于 .c和.cpp文件,g++则统一当做cpp文件编译
误区二:编译只能使用gcc,连接只能使用g++
这句话混淆了概念。编译可以用 gcc 或 g++,而链接可以用 g++ 或者 gcc-lstdc++。
因为 gcc 命令不能自动和 C++ 库链接,所以通常使用 g++ 来完成链接。
但在编译阶段,g++ 会自动调用 gcc,二者等价。

在编译阶段,g++会调用gcc,对于c++代码,两者是等价的,但是因为gcc命令不能自动和C++程序使用的库联接,所以通常用g++来完成链接,为了统一起见,干脆编译/链接统统用g++了,这就给人一种错觉,好像cpp程序只能用g++似的。

误区三:extern “C” 与 gcc/g++ 有关系
实际上并无关系,
无论是 gcc 还是 g++,用 extern “c” 时,都是以 C 的命名方式来为symbol 命名,
否则,都以 C++ 方式为函数命名。

这里以reciprocal.cpp为例:

#include <cassert>
#include "reciprocal.hpp"
double reciprocal (int i) {
    // I should be non-zero.
    assert (i != 0);
    return 1.0/i;
}
1
2
3
4
5
6
7
8
1) 未加 extern “c”时,reciprocal.hpp代码为:

 //一段代码
    extern double reciprocal (int i);
1
2
命令:
g++ -S reciprocal.cpp
less reciprocal.s
使用gcc和g++编译运行结果:


未加extern “C”时,函数reciprocal用gcc和g++编译得到的函数名是一样的,都是以C++的命名方式。
2) 加 extern “c”时,reciprocal.hpp代码为:

 extern "C" {
    //一段代码
    extern double reciprocal (int i);
}
1
2
3
4
使用gcc和g++编译运行结果:


也就是说,添加extern “C”后,函数reciprocal用gcc和g++编译得到的函数名是一样的,都是以C的命名方式。

由此可见,extern “C”与采用gcc/g++并无关系。

误区四:gcc不会定义__cplusplus宏,而g++会
实际上,这个宏只是标志着编译器将会把代码按C还是C++语法来解释,如上所述,如果后缀为.c,并且采用gcc编译器,则该宏就是未定义的,否则,就是已定义。

gcc在编译.c文件时,可使用的预定义宏是比较少的,很多都是未定义的。
gcc在编译cpp文件时、g++在编译c文件和cpp文件时(这时候gcc和g++调用的都是cpp文件的编译器),会加入一些额外的宏,这些宏如下:

#define __GXX_WEAK__ 1
#define __cplusplus 1
#define __DEPRECATED 1
#define __GNUG__ 4
#define __EXCEPTIONS 1
#define __private_extern__ extern
1
2
3
4
5
6
因此,我们总是会看到如下格式的代码(功能是对编译器提示使用C的方式来处理函数):
其中,__cplusplus是c++定义的宏,如果gcc在编译cpp文件时、g++在编译c文件和cpp文件时,extern c声明会有效。如果是gcc在编译.c文件时,那么,extern c声明无效。

#ifdef __cplusplus 
extern "C" { 
#endif

//一段代码

#ifdef __cplusplus 

#endif 
1
2
3
4
5
6
7
8
9
为什么需要使用extern “C”呢?C++之父在设计C++之时,考虑到当时已经存在了大量的C代码,为了支持原来的C代码和已经写好C库,需要在C++中尽可能的支持C,而extern “C”就是其中的一个策略。

试想这样的情况:一个库文件已经用C写好了而且运行得很良好,这个时候我们需要使用这个库文件,但是我们需要使用C++来写这个新的代码。如果这个代码使用的是C++的方式链接这个C库文件的话,那么就会出现链接错误。

C和C++对函数的处理方式是不同的。extern“C”是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern “C”来说明。
————————————————
版权声明:本文为CSDN博主「wsqyouth」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013457167/article/details/80222557

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gcc与g++的区别 的相关文章

随机推荐

  • 秒杀系统的思考

    极限并发带来的思考 虽然现在大多数情况下都能订到票 xff0c 但是放票瞬间即无票的场景 xff0c 相信大家都深有体会 尤其是春节期间 xff0c 大家不仅使用 12306 xff0c 还会考虑 智行 和其他的抢票软件 xff0c 全国上
  • 为什么禁止MyBatis批量插入几千条数据使用foreach?

    近日 xff0c 项目中有一个耗时较长的Job存在CPU占用过高的问题 xff0c 经排查发现 xff0c 主要时间消耗在往MyBatis中批量插入数据 mapper configuration是用foreach循环做的 xff0c 差不多
  • SpringBoot 那些天生自带 Buff 的工具类

    断言 断言是一个逻辑判断 xff0c 用于检查不应该发生的情况 Assert 关键字在 JDK1 4 中引入 xff0c 可通过 JVM 参数 enableassertions开启 SpringBoot 中提供了 Assert 断言工具类
  • SpringBoot四大核心组件

    前言 先透露一下 xff0c 四大组件分别是 xff1a starter xff0c autoconfigure CLI 以及actuator 下面我们就来详细介绍一些他们有什么用 一 Spring Boot Starter 1 1 Sta
  • 线上问题排查,这些命令你一定用得到!

    线上问题排查 xff0c 以下场景 xff0c 你遇到过吗 xff1f 一 了解机器连接数情况 问题 xff1a 1 2 3 4的sshd的监听端口是22 xff0c 如何统计1 2 3 4的sshd服务各种连接状态 TIME WAIT C
  • linux内核发包工具pktgen

    pktgen使用说明 内核路径 net core pktgen c 作者对于pktgen的介绍 xff1a 原作者编写的pdf介绍 pktgen c 原理介绍 pktgen运用了proc 文件系统特征来实现用户和内核的交互 xff0c 用户
  • 用css写进度条

    用css写进度条 我们平时写进度条一般是一个父div包裹一个子div xff0c 用js控制子div的宽度 实现进度条 xff0c 我们现在可以用css简单实现进度条了 代码如下 xff1a 在vue项目里咱们只需要控制数字就行了 xff0
  • SpringBoot集成SpringSecurity

    SpringSecurity 安全简介 在 Web 开发中 xff0c 安全一直是非常重要的一个方面 安全虽然属于应用的非功能性需求 xff0c 但是应该在应用开发的初期就考虑进来 如果在应用开发的后期才考虑安全的问题 xff0c 就可能陷
  • 【ElementUI】进度条 el-progress—进度圆环颜色、自定义文字

    圆环不显示 大概率是因为宽度没有设置 el progress width 100 圆圈背景色 lt el progress type 61 34 circle 34 percentage 61 34 20 34 class 61 34 pe
  • linux使用curl加双引号进行转义

    amp 是个特殊符号 xff0c 如果在控制台使用curl curl http 127 0 0 1 8089 ceshi startTime 61 2018 10 24 02 49 35 amp amp endTime 61 2018 10
  • qt程序的CMakeLists.txt配置转为平台的qt的.pro项目工程文件

    参考这个 跨平台qt程序的CMakeLists txt配置转为平台的qt的 pro项目工程文件 谁能懂我2011的博客 CSDN博客 一些比较正规的跨平台qt项目没有 pro项目文件只有CMakeLists txt文件 xff0c 如果要编
  • 单片机堆栈是什么?它的原理和作用又是什么?

    什么是单片机堆栈 xff1f 在片内RAM中 xff0c 常常要指定一个专门的区域来存放某些特别的数据 它遵循顺序存取和后进先出 LIFO FILO 的原则 这个RAM区叫堆栈 它的作用 子程序调用和中断服务时CPU自动将当前PC值压栈保存
  • IMU(陀螺仪、加速度计)&Magnetometer(磁力计)校准方法和流程

    一 何为校准 xff1a 校准的目的是因为厂商在生产器件时 xff0c 由于工艺 技术等原因 xff0c 致使器件存在缺陷 xff0c 导致实际应用时 xff0c 存在误差 xff01 一般器件在出厂时 xff0c 都会做一些校准处理 xf
  • matlab运行RTKDEMO几个小函数

    一 matlab函数 xff1a 1 datenum 将时间点转换为0000年1月0日到现在的天数 xff01 其中起点为 xff1a 0000年1月0日 例如 xff1a K gt gt t0 61 datenum 2005 4 2 0
  • 糖儿飞教你学C++ Socket网络编程——8. 异步通信版的TCP通信程序

    项目3 3中实现的通信程序仍然有很多不足 xff0c 最明显的不足是 xff0c 通信双方不能自动接收对方消息 xff0c 需要单击 接收 按钮才能接收 另外的问题是 xff0c 在服务器端单击 创建服务器 按钮后 xff0c 如果没有客户
  • VINS-Mono

    文章目录 初始化框架缺点ORB SLAM的Local Map VINS的滑窗 逐次逼近式去畸变给后端提供的特征点信息光流追踪对极约束F去除外点 rejectWithF 特征点均匀化预积分系统初始化初始化时不校正bias a误差卡尔曼滤波误差
  • python-异常

    https docs python org 3 library exceptions html 异常 程序在运行过程中 xff0c 不可避免的出现一些错误 没有赋值的变量使用了不存在的索引除0 这些错误在程序中 xff0c 称为异常程序运行
  • STM32CubeMX串口USART中断发送接收数据

    本文代码使用 HAL 库 文章目录 前言一 中断控制二 USART中断使用1 中断优先级设置 xff1a 2 使能中断3 使能UART的发送 接收中断4 中断收发函数5 中断处理函数6 中断收发回调函数 三 串口中断实验串口中断发送数据点亮
  • 关于gcc、make和CMake的区别

    CMake是一种跨平台编译工具 xff0c 比make更为高级 xff0c 使用起来要方便得多 CMake主要是编写CMakeLists txt文件 xff0c 然后用cmake命令将CMakeLists txt文件转化为make所需要的m
  • gcc与g++的区别

    一 编译的四个阶段 预处理 xff1a 编译处理宏定义等宏命令 xff08 eg define xff09 生成后缀为 i 的文件 编译 xff1a 将预处理后的文件转换成汇编语言 生成后缀为 s 的文件 汇编 xff1a 由汇编生成的文件