gcc与g++的比较以及库的使用说明

2023-05-16

一:gcc与g++比较

编 译c/c++代码的时候,有人用gcc,有人用g++,于是各种说法都来了,譬如c代码用gcc,而c++代码用g++,或者说编译用gcc,链接用 g++,一时也不知哪个说法正确,如果再遇上个extern "C",分歧就更多了,这里我想作个了结,毕竟知识的目的是令人更清醒,而不是更糊涂。
 
误区一:gcc只能编译c代码,g++只能编译c++代码
两者都可以,但是请注意:

1.后缀为.c的,gcc把它当作是C程序,而g++当作是c++程序;后缀为.cpp的,两者都会认为是c++程序,注意,虽然c++是c的超集,但是两者对语法的要求是有区别的,例如:

#include <stdio.h>
int main(int argc, char* argv[])
{
   if(argv == 0) return 0;
   printString(argv);
   return 0;
}
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“;

2.编译阶段,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 0;
}

1. 先给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
完全相同!
               
2. 去掉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的。

二:gcc和g++的包含头文件库文件方法

-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。

好 了现在我们知道怎么得到库名,当我们自已要用到一个第三方提供的库名字libtest.so,那么我们只要把libtest.so拷贝到/usr/lib 里,编译时加上-ltest参数,我们就能用上libtest.so库了(当然要用libtest.so库里的函数,我们还需要与libtest.so配 套的头文件)

放 在/lib和/usr/lib和/usr/local/lib里的库直接用-l参数就能链接了,但如果库文件没放在这三个目录里,而是放在其他目录里,这 时我们只用-l参数的话,链接还是会出错,出错信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了,比如常用的X11的库,它在/usr /X11R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录下,那链接参数就是-L /aaa/bbb/ccc -ltest

另外,大部分libxxxx.so只是一个链接,以RH9为例,比如libm.so它链接到/lib/libm.so.x,/lib/libm.so.6又链接到/lib/libm-2.3.2.so,

如果没有这样的链接,还是会出错,因为ld只会找libxxxx.so,所以如果你要用到xxxx库,而只有libxxxx.so.x或者libxxxx-x.x.x.so,做一个链接就可以了ln -s libxxxx-x.x.x.so libxxxx.so

手工来写链接参数总是很麻烦的,还好很多库开发包提供了生成链接参数的程序,名字一般叫xxxx-config,一般放在/usr/bin目录下,比如

gtk1.2的链接参数生成程序是gtk-config,执行gtk-config --libs就能得到以下输出"-L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic

-lgmodule -lglib -ldl -lXi -lXext -lX11 -lm",这就是编译一个gtk1.2程序所需的gtk链接参数,xxx-config除了--libs参数外还有一个参数是--cflags用来生成头 文件包含目录的,也就是-I参数,在下面我们将会讲到。你可以试试执行gtk-config --libs --cflags,看看输出结果

现 在的问题就是怎样用这些输出结果了,最笨的方法就是复制粘贴或者照抄,聪明的办法是在编译命令行里加入这个`xxxx-config --libs --cflags`,比如编译一个gtk程序:gcc gtktest.c `gtk-config --libs --cflags`这样就差不多了。注意`不是单引号,而是1键左边那个键。

5、-include和-I参数

-include 用来包含头文件,但一般情况下包含头文件都在源码里用#include xxxxxx实现,-include参数很少用。-I参数是用来指定头文件目录,/usr/include目录一般是不用指定的,gcc知道去那里找,但 是如果头文件不在/usr/include里我们就要用-I参数指定了,比如头文件放在/myinclude目录里,那编译命令行就要加上-I /myinclude参数了,如果不加你会得到一个"xxxx.h: No such file or directory"的错误。-I参数可以用相对路径,比如头文件在当前目录,可以用-I.来指定。

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

gcc与g++的比较以及库的使用说明 的相关文章

随机推荐

  • 记录远程桌面到Ubuntu2204

    以下操作都是以root权限进行 环境 xff1a ubuntu 22 04 1 desktop amd64 iso 安装的带有gui界面 已初始化root密码 1 安装软件 apt install xrdp xfce4 y 2 编辑xrdp
  • linux环境C程序设计--安装D-Bus

    根据书上写的指令进行操作 xff0c 结果显示错误在安装dbus 1 dbg的时候错误 xff0c 具体原因没仔细看 xff0c 但是下面提供了另一个安装的替换选项 xff0c 其命令如下 xff1a 安装GTK 43 开发包 xff0c
  • iOS开发笔记之NSFileManager的使用

    对于文件的管理 xff0c 从项目需求中出发 xff0c 有如下的学习成果 查看文档基本能完成基本的需求 文档中部分常用的方法 xff1a xff08 基本基于path和URL成对存在 xff0c 这里主要解读关于path的 xff09 获
  • 基于 FFmpeg 的播放器 demo

    这里的播放器演示程序用于播放一个本地文件 xff0c 因而不需要关心播放网络上的媒体数据时的网络传输问题 对于播放本地媒体文件的播放器来说 xff0c 所要完成的工作主要包括 xff1a 解封装 gt 音频解码 视频解码 gt 对于音频来说
  • mysql查看当前使用的配置文件my.cnf的方法

    1 查看是否使用了指定目录下的my cnf my cnf是mysql启动时加载的配置文件 xff0c 一般会放在mysql的安装目录中 xff0c 用户也可以放在其他目录加载 安装mysql后 xff0c 系统中会有多个my cnf文件 x
  • JUC中对线程的协同合作控制

    线程的协同合作控制 CountDownLatch使用代码演示小结 Semaphore使用小结 Condition使用代码 CyclicBarrier使用 xff1a 代码演示 小结 在使用多线程的时候 xff0c 我们可以使用一些工具来达到
  • Ubuntu+Anaconda+TA-Lib

    查看ubuntu版本 span class token function cat span etc issue 更换apt源 1 备份原有软件源 sudo cp etc apt sources list etc apt sources li
  • 服务器配置公网ftp服务端(软件和python代码两种方法)

    FileZilla Server超详细配置 前言一 配置教程1 General settings xff08 常规设置 xff09 2 Passive mode settings xff08 被动传输模式设置 xff09 3 Securit
  • 使用FFmpeg生成高清gif图

    前言 使用FFmpeg能够很方便的给视频片段或GIF加水印 xff0c 同时还能对选取的片段生成GIF图 xff0c 但是在使用默认FFmpeg设置情况下 xff0c 生成的GIF画质很差 xff0c 有很明显的栅格化现象 如何生成高质量的
  • PostgreSQL的SSL部署

    随着云服务器的兴起 xff0c 越来越多的数据库服务器被安装在远程 用SSL连接代替明文连接 xff0c 是数据库的基本安全功能 很庆幸PostgreSQL很早就支持openSSL xff0c 各发行版本都带有openSSL连接库 xff0
  • 八数码问题是否有解

    八数码问题 描述 xff1a 3 3的棋盘有八个数字 xff08 1 8 xff09 和一个空位 xff0c 数字可以滑动 问题研究的是从一个棋盘状态到另一个状态 是否有解的判定 12345678 对于上面的棋盘状态 xff0c 我们可以表
  • xrdp和vnc的区别

    在很多场景下 xff0c 我们需要远程连接到Linux服务器 本文是Ubuntu xff0c 传统的连接主要分为两种 第一种 xff1a 通过SSH服务 xff08 使用xshell等工具 xff09 来远程访问 xff0c 编写终端命令
  • 和风天气API数据分析

    注册和风天气获取key 请求数据时需要用到 xff0c 具体可查看文档 请求数据示例 3 10天天气预报 34 HeWeather6 34 34 basic 34 34 cid 34 34 CN101010100 34 34 locatio
  • 提供python接口有用的库

    python版本 windows上使用的是python2 7 2 32位版本 如何查看python是32位还是64位 xff1a import struct struct calcsize 34 P 34 如果是4 xff0c 说明是32位
  • Linux添加库路径的两种方法

    库文件在连接 静态库和共享库 和运行 仅限于使用共享库的程序 时被使用 xff0c 其搜索路径是在系统中进行设置的 一般 Linux 系统把 lib 和 usr lib 两个目录作为默认的库搜索路径 xff0c 所以使用这两个目录中的库时不
  • 动态库和静态库在编译C语言时使用方法简述

    函数库分为静态库和动态库两种 创建Linux静态库和Linux动态库和使用它们在这里将以举例的形式详述一下 静态库在程序编译时会被连接到目标代码中 xff0c 程序运行时将不再需要该静态库 动态库在程序编译时并不会被连接到目标代码中 xff
  • Linux下的tar压缩解压缩命令详解

    tar c 建立压缩档案 x xff1a 解压 t xff1a 查看内容 r xff1a 向压缩归档文件末尾追加文件 u xff1a 更新原压缩包中的文件 这五个是独立的命令 xff0c 压缩解压都要用到其中一个 xff0c 可以和别的命令
  • Linux环境下安装MATLAB2012

    在GNU Debian环境下 xff0c 使用iso镜像安装Matlab2012 xff0c 首先需要用mount命令挂载镜像 xff0c mount o loop t iso9660 source mount point 具体的讲 mou
  • string与string.h以及cstring的关系区别

    c 43 43 中 string与string h 的作用和区别 如下代码 include lt string h gt void main string aaa 61 34 abcsd d 34 printf 34 looking for
  • gcc与g++的比较以及库的使用说明

    一 xff1a gcc与g 43 43 比较 编 译c c 43 43 代码的时候 xff0c 有人用gcc xff0c 有人用g 43 43 xff0c 于是各种说法都来了 xff0c 譬如c代码用gcc xff0c 而c 43 43 代