gcc编译器

​ 这东西是Linux上的c/c++编译器。

5-1 gcc的工作流程

5-2 gcc的常用参数

-v 查看gcc版本号, --version也可以

-E 生成预处理文件

-S 生成汇编文件

-c 只编译, 生成.o文件, 通常称为目标文件

-I 指定头文件所在的路径

-L 指定库文件所在的路径

-l 指定库的名字

-o 指定生成的目标文件的名字

-g 包含调试信息, 使用gdb调试需要添加-g参数

-On n=0∼3 编译优化,n越大优化得越多

​ 例如:下面代码片段

​ int a = 10;

​ int b = a;

​ int c = b;

​ printf("%d", c);

​ 上面的代码可能会被编译器优化成:

​ int c = 10;

​ printf("%d", 10);

-Wall 提示更多警告信息

​ int a;

​ int b;

​ int c = 10;

​ printf(“[%d]\n”, c);

​ 编译如下:

​ gcc -o test -Wall test.c

​ warning: unused variable ‘b’ [-Wunused-variable]

​ warning: unused variable ‘a’ [-Wunused-variable]

-D 编译时定义宏

​ test.c文件中的代码片段:

printf("MAX==[%d]\n", MAX);

​ 编译:

​ gcc -o test test.c -D MAX=10

​ //gcc -o test test.c -DMAX=10

5-3 静态库

​   这个东西是源文件的另一种表现形式,是一种加了密的源代码,将可以实现某些功能的函数的集合体。

​   一般我们会拿到一个后缀为“.a”的库文件和一个头文件“.h”。之后在源代码中包含这个头文件,然后在编译 指令上加上库的名字,来使用库。

​ 静态库分为三部分 前缀 库名称 后缀

前缀统一为:lib

库的名字随意,记得别和某些关键字(如int)相同。

后缀统一为:.a

​ 最终静态库名字为:libXXX.a

静态库的制作:

​ 假设我们有一个头文件(head.h)两个源文件(one.c , two.c),其中头文件中是函数/变量的声明,其 中在one.c 和 two.c 中是函数的实现。

​ 第一步:让源文件 .c 生成对应的 .o 文件

gcc -c one.c two.c

​ 第二步:使用打包工具ar将刚才生成好的 .o 文件打包到一块成为 .a 文件

​ ar工具的语法:

ar 参数 静态库名 .o文件

参数:r为更新 c为创建 s为建立索引

这里的静态库名要把中间,前后缀写全。

命令:ar rcs libtest1.a one.o two.o

静态库的使用:

​ 制作完成后记得把库文件(.a) 和 头文件(.h) 一并发给用户。

​ 假设有一个源文件main.c要使用静态库libtest.a,那就得先在main.c中包含头文件head.h 然后使用 指令进行编译。

gcc参数:

	 **-L**:指定要连接的库的所在目录

	 **-l**:指定链接时需要的静态库, 去掉前缀和后缀

	 **-I**: 指定main.c文件用到的头文件head.h所在的路径

输入命令:gcc -o main1 main.c -L./ -ltest1 -I./ 即可完成编译

静态库的优缺点:

优点

​ 1.静态库只需将库文件链接到可执行文件中,无需额外的动态链接步骤。(和源文件一块编译)

​ 2.因为静态库会和源文件一起打包为可执行程序,使用在部署和分发时更加独立,不需要再准备什么 额外的库文件。

​ 3.静态库在编译阶段可以被gcc中的 -On优化,从而提高代码的效率。

缺点

​ 1.它会直接将自己和源文件一起打包为可执行程序,所以会增加可执行文件的大小。

​ 2.如果需要更新静态库,则需要重新编译整个程序。

​ 3.如果多线程/进程使用的应用程序是相同的静态库,则每个应用程序都会有一份静态库的副本,造成资源浪费。

5-4动态库/静态库

​   动态库在编译阶段不会被链接到代码中,而是在程序运行时被载入。假设我们有n个不同的程序都要调用 该动态库,那么在内存中只需要有一份该动态库的拷贝,然后其他n个程序就可以调用了,与静态库相比,动 态库大大地节省了内存空间,而且动态库也方便于更新维护,多个程序共享一个动态库,我们每次更新只需要 更新该库即可;而不是像静态库那样还要重新编译文件。动态库一般以“.so”作为后缀名。

​ 动态库的命名分为三个部分:前缀 名称 后缀

前缀:lib

库名称:自定义,记得绕开某些关键字(如int)

后缀:.so

​ 最终的名字为:libXXX.so

动态库的制作:

​ 假设有源文件one.c two.c 头文件head.h,其中头文件是函数/变量的声明,具体的函数实现在源文件 one.c 和 two.c中。

第一步:先生成目标文件,记得此时要加编译选项(-fpic)。

gcc -fpic -c one.c two.c

​ 参数-fpic可以让编译出来的东西可以被共享。

第二步:生成库文件,记得此时要加链接选项(-shared)它可以生成指定动态链接库。

gcc -shared one.c two.c -o libtest.so

动态库的使用:

​ 当拿到.so的库文件和与之对应的头文件后,记得在源代码中包含该头文件。

	**-L**:指定要连接的库的所在目录

	 **-l**(小写的L):指定链接时需要的动态库, 去掉前缀和后缀

	 **-I** (大写的i): 指定main.c文件用到的头文件head.h所在的路径

命令: gcc main.c -l./ -L./ -Itest -o main

​ 因为动态库是多程序共享的,所以要让main知道我们的动态库具体在什么位置,可以输入:ldd main 命 令来查看程序main所依赖的动态库在哪里。

​ 很明显,not found是找不到的意思,那么我们

对于elf格式的可执行程序,是由ld-linux.so*来完成的, 它先后搜索elf文件的 DT_RPATH段 — 环境变量LD_LIBRARY_PATH — /etc/ld.so.cache文件列表 — /lib/, /usr/lib目录找到库文件后将其载入内存。

使用file命令可以查看文件的类型:

如何让系统找到共享库:

拷贝自己制作的共享库到/lib或者/usr/lib

方法一:临时设置LD_LIBRARY_PATH:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径

方法二:永久设置, 把export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径, 设置到∼/.bashrc文件中, 然 后在执行下列三种办法之一:

​ 执行. ~/.bashrc使配置文件生效(第一个.后面有一个空格)

​ 执行source ~/.bashrc配置文件生效

​ 退出当前终端, 然后再次登陆也可以使配置文件生效

方法三:永久设置,把export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径,设置到/etc/profile文件中。

方法四:将其添加到 /etc/ld.so.cache文件中

​ 编辑/etc/ld.so.conf文件, 加入库文件所在目录的路径

​ 运行sudo ldconfig -v, 该命令会重建/etc/ld.so.cache文件

**解决了库的路径问题之后, 再次ldd命令可以查看可执行文件依赖的库文件, ldd main

共享库的优缺点:

​ 优点:

​ 1.节省内存。

​ 2.方便更新。

​ 缺点:

​ 1.因为在程序运行时才会载入,所以加载速度不快。

​ 2.移植性差,每次移植都得把所有相关动态库移植走。

Linux下的gcc/g++编译器的使用 [补档-2023-06-13]的更多相关文章

  1. [转]Linux下用gcc/g++生成静态库和动态库(Z)

    Linux下用gcc/g++生成静态库和动态库(Z) 2012-07-24 16:45:10|  分类: linux |  标签:链接库  linux  g++  gcc  |举报|字号 订阅     ...

  2. Linux环境下GNU, GCC, G++编译器

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012823258/article/details/36890125 一.GNU GNU是" ...

  3. Linux环境下GNU, GCC, G++编译器(转)

    一,GNU GNU是“GNU 's Not Unix”的递归缩写, Stallman宣布GNU应当发音为Guh-NOO(革奴)以避免与new这个单词混淆(注:Gnu在英文中原意为非洲牛羚,发音与new ...

  4. linux下使用gcc/g++编译代码时gets函数有错误

    今天在linux中使用个g++编译一个名为myfirst.cpp的代码的时候,出现如下错误 myfirst.cpp: In function ‘int main()’:myfirst.cpp:11:2 ...

  5. gcc/g++编译器的安装与说明

    gcc/g++编译器的安装与说明 1.gcc/g++编译器的安装 gcc yum install gcc g++ yum install gcc-c++ 2.gcc/g++的作用 将c/c++源代码编 ...

  6. Linux下用GCC

    Linux下用GCC 前言 离职前对做过的支付系统进行了一番#总结,继续完善我的C服务器. 本想着接下来大概实现一下 CGI 协议,但是实现过程中被一个问题卡住了: C进程与php进程的交互数据类型问 ...

  7. Linux下安装gcc 、g++ 、gfortran编译器

    一.ubuntu下gcc/g++/gfortran的安装 1.安装 (1).gcc ubuntu下自带gcc编译器.可以通过“gcc -v”命令来查看是否安装. (2).g++ 安装g++编译器,可以 ...

  8. Windows Sublime Text 配置Linux子系统(WSL)下的 gcc/g++ 编译环境

    0. 简介(若已了解背景可以跳过此部分) Windows 10 Build 14316以上版本中加入了"Windows系统的Linux子系统"(Windows Subsystem ...

  9. linux下使用gcc编译运行C程序

    gcc(GNU Compiler Collection)是Linux下最常用的C语言编译器,是GNU项目中符合ANSI C标准的编译系统,能够编译用C.C++和Object C等语言编写的程序.  在 ...

  10. linux下使用gcc编译运行C/C++程序

    编译C  首先,程序编译过程有: 1.预处理(展开宏,头文件,检查代码是否有误) 2.编译(将.c转为汇编代码.s) 3.汇编(将汇编代码.s转为机器代码.o) 4.链接(将所有机器代码.o和库文件链 ...

随机推荐

  1. 【JAVA基础】Swagger使用

    Swagger使用 刷新权限 自定标签名称

  2. C. Given Length and Sum of Digits... (贪心)

    https://codeforces.com/problemset/problem/489/C C. Given Length and Sum of Digits... You have a posi ...

  3. 服务降级,限流等--sentinel(SpringCloud Alibaba)

    一. 介绍Sentinel,中文翻译为哨兵,是为微服务提供流量控制.熔断降级的功能,它和Hystrix提供的功能一样,可以有效的解决微服务调用产生的"雪崩"效应,为微服务系统提供了 ...

  4. 【内核】深入分析内核panic(三)--内核错误处理流程

    1 内核错误处理方式 当内核出现致命错误时,只要cpu还能正常运行,那么最重要的就是向用户输出详细的错误信息,以及保存问题出现时的错误现场.以上致命错误可包含以下两种类型: (1)硬件能检测到的错误, ...

  5. 扒一扒ProcessOn 新功能——一键编号、图形组合、左侧导航、画布水印、表格组件

    思维导图.一键编号 思维导图新增 多种全新主题风格,让您的创作赏心悦目 思维导图新增 一键编号 功能 流程图.图形组合 自定义组合图形功能:新增流程图 我的图形 功能,用户可以设置或者上传自己的图形 ...

  6. 定期发送邮件功能-outlook与腾讯邮箱

    一.背景:定期发送邮件功能挺好用的,可以帮忙我们在特殊的时间点发送邮件,以及实现无人推送的功能 二.outlook的实现1.首先编辑好邮件保存至草稿 2.选项-延迟传递,设置不早于传递的时间,点击发送 ...

  7. Nacos源码 (6) Grpc概述与Nacos集成

    Nacos 2.x版本增加了GRPC服务接口和客户端,极大的提升了Nacos的性能,本文将简单介绍grpc-java的使用方式以及Nacos中集成GRPC的方式. grpc-java GRPC是goo ...

  8. 在Vue中可以使用方括号法获得想要的对象数据吗?

    1.问题 Document {{message}} {{school.name}}{{school[mobile]}} 在这里 {{school.name}}{{school[mobile]}} 不可 ...

  9. Laravel - Eloquent 删除数据

        public function ormDelete()     {         # 1.通过模型删除         // $student = Student::where('id',5 ...

  10. WebApi的输出结果重写 OnActionExecuted

    public override void OnActionExecuted(ActionExecutedContext context) { if (context.Exception != null ...