当前位置: 首页 > news >正文

C语言编译过程

C语言编译过程

  • 1、C语言编译过程
  • 2、单c文件编译实践
  • 3、多c文件编译实践
  • 4、define
    • 4.1、不带参宏
    • 4.2、带参宏
    • 4.3、带参宏和带参函数的区别
  • 5、选择性编译ifdef、ifndef、if
    • 5.1、#ifdef
    • 5.2、#ifndef
    • 5.3、#if
  • 6、静态库和动态链接库
    • 6.1、静态库实践
      • 6.1.1、将mylib.c制作成静态库
      • 6.1.2、编译源程序
    • 6.2、动态库实践
      • 6.2.1、将mylib.c制作成动态链接库
      • 6.2.2、动态链接库的使用

1、C语言编译过程

1、预编译
.c 中的头文件展开、宏展开。生成的文件是 .i 文件。预处理操作过程不会进行语法检查。
2、编译
将预处理之后的 .i 文件生成 .s 汇编文件
3、汇编
.s 汇编文件生成 .o 目标文件
4、链接
.o 文件链接成 可执行目标文件

2、单c文件编译实践

hello.c文件

#include<stdio.h>int main() {printf("Hello World! \n");return 0;
}
Linux 下GCC 编译器编译过程
1、预处理
gcc -E hello.c -o hello.i
2、编译
gcc -S hello.i -o hello.s
3、汇编
gcc -c hello.s -o hello.o
4、链接
gcc hello.o -o hello

3、多c文件编译实践

#include<xxx.h> // 用尖括号包含头文件,在系统指定的路径下找头文件
#include "xxx.h" // 用双引号包含头文件,先在当前目录下找头文件,找不到,再到系统指定的路径下找。
注意:include 经常用来包含头文件,可以包含.c 文件,但是大家不要包含.c。
因为 include 包含的文件会在预编译被展开,如果一个.c 被包含多次,展开多次,会导致函数重复定义。所以不要包含.c 文件。

test.c文件

#include<stdio.h>
#include "max.h"
#include "min.h"int main() {int maxVal = max(1, 5);int minVal = min(1, 5);printf("最大值maxVal = %d;最小值minVal = %d \n", maxVal, minVal);return 0;
}

max.c文件

int max(int v1, int v2) {int z;if (v1>v2) {z = v1;}else {z = v2;}return z;
}

min.c文件

int min(int v1, int v2) {int z;if (v1 < v2) {z = v1;}else {z = v2;}return z;
}

max.h文件

extern int max(int v1, int v2);

min.h文件

extern int max(int v1, int v2);
gcc -E test.c -o test.i
gcc -S test.i -o test.s
gcc -c test.s -o test.ogcc -E max.c -o max.i
gcc -S max.i -o max.s
gcc -c max.s -o max.ogcc -E min.c -o min.i
gcc -S min.i -o min.s
gcc -c min.s -o min.ogcc test.o max.o min.o -o test

4、define

定义宏用 define 关键字,宏是在预编译的时候进行替换。

4.1、不带参宏

#define PI 3.1415926

在预编译的时候如果代码中出现了 PI 就用 3.1415926 去替换。
宏定义的好处:只要修改宏定义,其他地方在预编译的时候就会重新替换。
注意:宏定义后边不要加分号。

宏定义的作用范围:从定义的地方到本文件末尾。
如果想在中间终止宏的定义范围

//终止PI 的作用
#undef PI

4.2、带参宏

#define S(a,b) a*b

注意带参宏的形参 a 和 b 没有类型名:(注意歧义)
S(1,5) 即【1*5
S(3+4,3) 即【3+4 * 3
S((3+4),3) 即【(3+4)*3

4.3、带参宏和带参函数的区别

带参宏: 被调用多少次就会展开多少次,执行代码的时候没有函数调用的过程不需要压栈弹栈。所以带参宏,是浪费了空间,因为被展开多次,节省时间。
带参函数: 代码只有一份,存在代码段,调用的时候去代码段取指令,调用的时候要压栈弹栈。有个调用的过程。

带参函数是浪费了时间,节省了空间。
带参函数的形参是有类型的,带参宏的形参没有类型名。

5、选择性编译ifdef、ifndef、if

选择性编译都是在预编译阶段处理的事情。

5.1、#ifdef

#ifdef AAA代码段一
#else代码段二
#endif
#include<stdio.h>
#define AAAint main(int argc, char *argv[]){
#ifdef AAAprintf("Hello World!\n");
#elseprintf("Hello China!\n");
#endifreturn 0;
}

5.2、#ifndef

#ifndef AAA代码段一
#else代码段二
#endif

#ifndef#ifdef 是一种互补。这种方法,经常用在防止头文件重复包含。

5.3、#if

如果表达式为真,编译第一段代码,否则编译第二段代码。

#if 表达式程序段一
#else程序段二
#endif

6、静态库和动态链接库

一、动态编译
动态编译使用的是动态库文件进行编译,默认使用的就是动态编译。

gcc hello.c -o hello1

二、静态编译
静态编译使用的静态库文件进行编译。

gcc -static hello.c -o hello2

三、静态编译和动态编译区别
1、使用的库文件的格式不一样:动态编译使用动态库,静态编译使用静态库。
2、静态编译要把静态库文件打包编译到可执行程序中。
3、动态编译不会把动态库文件打包编译到可执行程序中,它只是编译链接关系。

=== mytest.c ====================================
#include <stdio.h>
#include "mylib.h"int main(int argc, char* argv[]) {int a = 10, b = 20, max_num, min_num;max_num = max_fun(a, b);min_num = min_fun(a, b);printf("max_num = %d \n", max_num);printf("min_num = %d \n", min_num);return 0;
}=== mylib.c ====================================
int max_fun(int x, int y) {return (x > y) ? x : y;
}int min_fun(int x, int y) {return (x < y) ? x : y;
}=== mylib.h ====================================
#ifndef __MYLIB_H__
#define __MYLIB_H__
extern int max_fun(int x, int y);
extern int min_fun(int x, int y);
#endif

6.1、静态库实践

6.1.1、将mylib.c制作成静态库

gcc -c mylib.c -o mylib.o
ar rc libmylib.a mylib.o

注意:静态库文件 起名的时候必须以 lib 开头以 .a 结尾

6.1.2、编译源程序

方法1:在同一目录下编译
编译源程序命令:

gcc -static mytest.c libmylib.a -o mytest

方法2:可以指定头文件及库文件的路径
如将 libmylib.a mylib.h 移动到 /root/staticlib

mv libmylib.a mylib.h /root/staticlib

编译源程序命令:

gcc mytest.c \
-static \
-o mytest \
-L /root/staticlib \
-l mylib \
-I /root/staticlib

注意:
-L 是指定库文件的路径
-l 指定找哪个库,指定的只要库文件名 lib 后面 .a 前面的部分
-I 指定头文件的路径

方法3:将库文件及头文件存放到系统默认指定路径
库文件 默认路径是 /lib 或者是 /usr/lib
头文件 默认路径是 /usr/include

mv libmylib.a /usr/lib
mv mylib.h /usr/include

编译源程序的命令

gcc mytest.c -o mytest -l mylib -static 

6.2、动态库实践

6.2.1、将mylib.c制作成动态链接库

使用gcc 编译、制作动态链接库

gcc -shared mylib.c -o libmylib.so

注意:动态链接库文件 起名的时候必须以 lib 开头以 .so 结尾

6.2.2、动态链接库的使用

方法1:库函数、头文件均在当前目录下

gcc mytest.c libmylib.so -o mytest
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH

此时就可以在执行了哦: ./mytest

方法2:库函数、头文件假设在 /opt/ 目录

mv libmylib.so mylib.h /opt
gcc mytest.c -o mytest -L/opt -lmylib -I/opt编译通过,运行 mytest 时出错,编译时找到了库函数,但运行链接时找不到库,要把链接库文件所在目录加入默认搜索路径
export LD_LIBRARY_PATH=/opt:$LD_LIBRARY_PATH

此时就可以在执行了哦: ./mytest

方法3:库函数、头文件均在系统路径下

cp libmylib.so /usr/lib
cp mylib.h /usr/include
gcc mytest.c -o mytest -lmylib

如果出现如下错误,则添加查找路径,解决问题

[root@michael cc]# ./mytest 
./mytest: error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or directory解决方案:
export LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH

此时就可以在执行了哦: ./mytest

注:
问:此时有个问题出现了?静态库 和 动态库 都在 /usr/lib 下,那么默认链接的到底是动态库还是静态库呢?
答:当静态库与动态库重名时,系统会优先连接动态库,或者编译时加入-static 指定使用静态库。

相关文章:

C语言编译过程

C语言编译过程1、C语言编译过程2、单c文件编译实践3、多c文件编译实践4、define4.1、不带参宏4.2、带参宏4.3、带参宏和带参函数的区别5、选择性编译ifdef、ifndef、if5.1、#ifdef5.2、#ifndef5.3、#if6、静态库和动态链接库6.1、静态库实践6.1.1、将mylib.c制作成静态库6.1.2、…...

前端学习 ---常用标签

常用标签 1,文本标签 文本标签是双标签&#xff0c;自带加粗效果&#xff0c;有自己对应的文本大小&#xff0c;并且独占一行&#xff0c;有默认间距 一级标签&#xff1a;< h1 > < /h1 > 二级标签&#xff1a;< h2 > < /h2> 三级标签&#xff1a;&l…...

2023年PMP考试难不难?

整个考试的考察方向转向还是比较大的&#xff0c;基本上以“价值传递”和“以人为本”这两个出发点来考察项目经理所需要的能力。 1}新版提纲题目数量的变化 总题量从200道减少到180道&#xff0c;所以答题时间上相对变的宽裕一些。考试时间230分钟&#xff0c;中间有十分钟休…...

Netty 入门

文章目录一、概述1.1 Netty 是什么&#xff1f;1.2 Netty 的地位1.3 Netty 的优势二、Hello World2.1 目标2.2 服务器端2.3 客户端2.4 流程梳理三、组件3.1 EventLoop3.2 演示 NioEventLoop 处理 io 事件3.3 演示 NioEventLoop 处理普通任务3.4 演示 NioEventLoop 处理定时任务…...

收藏|一文掌握数据分析在企业的实际流程

一、数据分析概念 1.1 数据分析 是指用适当的统计分析方法对收集来的大量数据进行分析&#xff0c;将他们加以汇总和理解并消化&#xff0c;以求最大化地开发数据的功能&#xff0c;发挥数据的作用。 1.2 数据分析包括 描述性数据分析&#xff08;初级数据分析&#xff09;…...

100ask_imx6ull 输出PWM

查看PWM对应扩展板的引脚 100ask_imx6ul通过扩展板插槽来验证pwm波&#xff0c;所以这里通过扩展板的原理图及芯片手册可知&#xff0c;gpio4_io20&#xff0c;gpio4_io19分别对应着PWM8和PWM7。 设置设备树 打开官方NXP的工具i.MX pins v6工具&#xff0c;PWM7/PWM8的配置如…...

yolov5编译安卓APP:解决图像上全是检测框

yolov5编译安卓APP&#xff1a;解决图像上全是检测框前言一、第一个YOLOv5 APP1.参考链接2.详细说明3.APP检测时图像上全是框的解决方法二、第二个YOLOv5 APP1.参考链接2.详细说明3.APP检测时图像上全是框的解决方法三、其他1.APK打包2.修改APP图标与名字前言 YOLOv5编译安卓A…...

为什么我们需要地图?

想一想&#xff0c;武侠小说里面。一张藏宝图&#xff0c;引来江湖腥风血雨&#xff0c;要么是武功秘籍&#xff0c;要么是绝世宝剑&#xff0c;要么是富可敌国的财富&#xff0c;只要有了藏宝图&#xff0c;便可曲径通幽&#xff0c;到达彼岸。 由此可见&#xff0c;地图的重…...

攻防世界1.新手练习区

4.攻防世界1.新手练习区 1.view_source 访问url&#xff1a; http://111.200.241.244:48855/ 鼠标点击右键不起作用&#xff0c;F12审查元素 得到flag为cyberpeace{0f3a3e4ab8c8664f3cf40d4240ec7b53} 2.robots 访问url&#xff1a; http://111.200.241.244:34362/ rob…...

Python进阶篇(二)-- Django 深入模型

上一节提到了Django是基于MVC架构的Web框架&#xff0c;MVC架构追求的是“模型”和“视图”的解耦合。所谓“模型”说得更直白一些就是数据&#xff08;的表示&#xff09;&#xff0c;所以通常也被称作“数据模型”。在实际的项目中&#xff0c;数据模型通常通过数据库实现持久…...

ABAP SALV实现弹出ALV选择

问题场景 需要弹出一个ALV并获取选择的数据 实现思路 跳转屏幕弹出ALV&#xff08;通过SALV&#xff09;弹出ALV&#xff08;通过REUSE_ALV_POPUP_TO_SELECT&#xff09; 实现效果 因为这里需要的是单选&#xff0c;所以没有多选列 实现代码 MODULE sel_zfretype INPUT.…...

git check-pick,git patch 与 git stash 详解

大家好&#xff0c;我是 17。 今天和大家聊一聊 git check-pick&#xff0c;git patch 与 git stash 的用法。 git cherry-pick 为什么要用 cherry-pick? 不适合 merge 的场景就可以考虑 cherry-pick。 试想下面这些场景 只想同步分支的部分提交。两个分支是两上完全独立…...

OA漏洞-到处搜集整理

一米OA getfile.jsp 任意文件读取漏洞 原文链接 漏洞复现 一米OA getfile.jsp 任意文件读取漏洞 一米OA协同办公系统,集成了OA办公自动化系统、手机客户端、专业报表工具,为全国千万企业用户提供全功能、性价比高的OA软件。一米OA getfile.jsp文件存在任意文件读取漏洞&am…...

web端接收读卡器卡片信息

项目背景 通过电脑连接的读卡器读取卡片信息&#xff0c;并由web页面接收和处理卡片信息。 读卡器抛出卡片信息流程 卡片贴近或放置到读卡器上读卡器解析卡片信息&#xff0c;并形成固定格式的字符串&#xff0c;包括的信息有&#xff1a;卡片写入的数据、卡片原数据&#x…...

BUUCTF-练习场-WEB-第一部分(8道)

[极客大挑战 2019]EasySQL 1payload&#xff1a;1 or 11#是闭合前面的查询语句&#xff0c;or 11恒成立&#xff0c;可以使用or句子绕过判断&#xff0c;#用于注释&#xff0c;注释后面的内容不再执行&#xff0c;所以该sql命令会返回表内所有内容&#xff0c;其实就是实现一个…...

Java Reflection 实战- Class类

Java Reflection 实战 - Class Java 反射使得在运行时检查类、接口、字段和方法成为可能&#xff0c;而不需要在编译时知道类、方法等的名称。也可以使用反射来实例化新对象、调用方法和获取/设置字段值。 Java反射的功能相当强大&#xff0c;可以说是非常有用。例如&#xff…...

背包问题理解思路(01背包、完全背包、分组背包)

这两天把经典的三个背包问题看了一下&#xff0c;网上大多文章是以代码和公式为主&#xff0c;因为平时没刷过算法题所以理解起来花了些时间&#xff0c;固写一篇文章记录理解思路&#xff0c;本文不包含代码实现&#xff08;理解了思路代码实现应该是小问题&#xff0c;网上一…...

Mr. Cappuccino的第39杯咖啡——Kubernetes之深入理解Pod

Kubernetes之深入理解PodPod相关概念Pod详细配置清单Pod核心配置Pod基本配置1. 创建yaml文件2. 创建namespace并根据yaml文件创建资源3. 查看namespace下的pod列表以及pod的详细信息Pod中多个容器的名称和端口号不能相同Pod镜像拉取策略Pod环境变量Pod端口相关设置Pod资源相关配…...

SqlSession 和 SqlSessionTemplate 简单使用及注意事项

1、SqlSession 简单使用 先简单说下 SqlSession 是什么&#xff1f;SqlSession 是对 Connection 的包装&#xff0c;简化对数据库操作。所以你获取到一个 SqlSession 就相当于获取到一个数据库连接&#xff0c;就可以对数据库进行操作。 SqlSession API 如下图示&#xff1a;…...

1. QSaveFile和QFile的简单使用

1. 说明 QSaveFile和QFile两个类都是用来操作文件的&#xff0c;区别在于QSaveFile在对文件进行写入时有一种保护机制&#xff0c;再写入出错时&#xff0c;不会对源文件中的内容进行操作。该类在执行写操作时&#xff0c;会先将内容写入到一个临时文件中&#xff0c;如果没有…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...