C语言-编译和链接

目录

    • 1.前言
    • 2.编译
      • 2.1预处理(预编译)
        • 2.1.1 #define 定义常量
        • 2.1.2 #define 定义宏
        • 2.1.3带有副作用的宏参数
        • 2.1.4宏替换规则
        • 2.1.5 #和##
          • 2.1.5.1 #运算符
            • 2.1.5.2 ## 运算符
        • 2.1.6 命名约定
        • 2.1.7 #undef
        • 2.1.8 条件编译
        • 2.1.9 头文件的包含
          • 2.1.9.1 本地文件包含
          • 2.1.9.2 库文件包含
        • 2.1.10 嵌套文件包含
    • 3.编译
    • 4.汇编
    • 5.链接

1.前言

在这里插入图片描述
一个C语言项目中可能有多个.c文件一起构建

  • 多个.c文件单独经过编译器,编译处理生成对应的目标文件
  • 多个目标文件和链接库一起经过链接器处理生成最终的可执行程序

2.编译

2.1预处理(预编译)

预处理阶段主要处理那些源文件中#开始的预编译指令。比如:#include,处理规则如下:

  • 将所有的#define删除,并展开所有的宏定义
  • 处理所有的条件编译指令
  • 删除所有的注释
  • 添加行号和文件名标识符,方便后续编译器生成调试信息
  • 处理#include预编译指令,将所包含的头文件的内容插入到该预编译指令的位置
2.1.1 #define 定义常量
#define MAX 100

在用#define定义标识符的时候,不用在最后加上;
如果加上,很容易导致一些问题

#define MAX 100;

int main()
{
	int a=0;
	if(1)
	a=MAX;//这里其实是  a=100;;  这里有两个分号,编译器会通不过,因为if只能管一条语句,两个分号就是两条语句
	else
	a=-1;
}
2.1.2 #define 定义宏

#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏
宏的声明方式:

#define name( parament-list ) stuff

注意:
参数列表的左括号必须与name紧邻!!!

举例:

#define SQUARE(x) ((x)*(x))

int a=4;
printf("%d\n",SQUARE(a+1));//25

提示:
用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏定义时由于参数中的操作符或邻近操作符之间不可预料的相互作用

#define SQUARE(x) x*x

int a=4;
printf("%d\n",SQUARE(a+1));//9
//a+1*a+1=4+4+1=9
2.1.3带有副作用的宏参数

当宏参数在宏定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果

x+1;//不带副作用的
x++;//带副作用的

举例:

#include <stdio.h>
#define MAX(a,b)  ((a++)>(b++)?(a++):(b++))
int main()
{
	int x=3;
	int y=4;
	printf("%d\n",MAX(x,y));//?
	printf("%d\n",x);//?
	printf("%d\n",y);//?
	return 0;
}
//((x++)>(y++)?(x++):(y++))
//MAX(x,y)=5
//x=4
//y=6
2.1.4宏替换规则
  • 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换
  • 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换
  • 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。

注意:
1.宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
2.当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

2.1.5 #和##
2.1.5.1 #运算符

#运算符将宏的一个参数转换成字符串字面量。它仅允许出现在带参数的宏的替换列表中
#运算符所执行的操作可以理解为“字符串化
比如:

//当我们有一个变量a=10;的时候,我们向打印出:the value of a is 10;
#define G(n) printf("the value of "#n " is %d",n);//n=10
//代码会转换成:
printf("the value od ""a" " is %d",a);
2.1.5.2 ## 运算符

##被称为记号粘合符
比如:
我们想写一个函数求两个数的较大值的时候,不同类型就得写不同的函数

int int_max(int x,int y)
{
	return x>y?x:y;
}

double double_max(double x,double y)
{
	return x>y?x:y;
}

这样写就比较繁琐

//宏定义
#define G_MAX(type)\
type type##_max(type x,type y)\
{\
	return x>y?x:y;\
}

G_MAX(int)//定义函数
G_MAX(double)//定义函数

int main()
{
 //调⽤函数
 int m = int_max(2, 3);
 printf("%d\n", m);//3
 double fm = double_max(3.5, 4.5);
 printf("%f\n", fm);//4.500000
 return 0;
 }
2.1.6 命名约定

把宏名全部大写
函数名不要全部大写

2.1.7 #undef

这条指令用于移除一个宏定义

#undef MAX
//如果现存的一个名字需要被重新定义,那么它的旧名字首先要被移除
2.1.8 条件编译

在编译一个程序的时候我们如果要将一条语句编译或者放弃是很方便的。因为我们有条件编译指令
比如:

#include <stdio.h>
#define __DEBUG__
int main()
{
	int a = 1;
	int b = 2;
	int x = 3;
#ifdef __DEBUG__
	printf("%d\n", a);
#endif
	printf("%d\n", b);
	printf("%d\n", x);

	return 0;
}

条件编译指令有很多,这里就不一一列举了

2.1.9 头文件的包含
2.1.9.1 本地文件包含
#include "filename"

查找策略:
先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标准位置查找头文件。如果找不到据提示编译错误

2.1.9.2 库文件包含
#include <filename>

查找头文件直接去标准路径下查找,找不到就提示编译错误

2.1.10 嵌套文件包含

如何解决头文件被重复引入的问题?
条件编译

#ifndef __TEST_H__
#define __TEST_H__
//头⽂件的内容
#endif //__TEST_H__

或者

 #pragma once

3.编译

编译过程就是将预处理后的文件进行一系列的:词法分析,语法分析,语义分析及优化,生成相应的汇编代码

4.汇编

汇编器是将汇编代码转转变成机器可执行的指令,每⼀个汇编语句几乎都对应⼀条机器指令。就是根
据汇编指令和机器指令的对照表⼀⼀的进行翻译,也不做指令优化。

5.链接

链接是⼀个复杂的过程,链接的时候需要把⼀堆⽂件链接在⼀起才生成可执行程序
链接过程包括:地址和空间分配,符号决议和重定位等步骤

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/502501.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于RIP的MGRE综合实验

实验拓扑&#xff1a; 实验要求&#xff1a; 1、R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;其所有地址均配为公有Ip地址; 2、R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证方&#xff1b; R2与R5之间使用ppp的cHAP认证&#xff0c;R5为主认证方; R3与R5之间使用H…

Clip算法解读

论文地址&#xff1a;https://arxiv.org/pdf/2103.00020.pdf 代码地址&#xff1a;https://github.com/OpenAI/CLIPz 中文clip代码&#xff1a;https://gitcode.com/OFA-Sys/Chinese-CLIP/overview 一、动机 主要解决的问题&#xff1a; 超大规模的文本集合训练出的 NLP 模…

pbrt-v4 windows编译失败指南

cpu下编译成功很容易&#xff0c;但是gpu有点麻烦&#xff0c;主要有下面几个坑 安装optix 7&#xff0c;cmake build 要加上PBRT_OPTIX_PATH cmake cuda 版本要对应&#xff0c;不然会出现 cuda not found&#xff0c;或者generate的时候报错&#xff0c;导致最后pbrt.exe --…

FANUC机器人故障诊断—报警代码更新(三)

FANUC机器人故障诊断中&#xff0c;有些报警代码&#xff0c;继续更新如下。 一、报警代码&#xff08;SRVO-348&#xff09; SRVO-348DCS MCC关闭报警a&#xff0c;b [原因]向电磁接触器发出了关闭指令&#xff0c;而电磁接触器尚未关闭。 [对策] 1.当急停单元上连接了CRMA…

在react项目用echarts绘制中国地图

文章目录 一、引入echarts二、下载地图json数据三、编写react组件四、组件使用 一、引入echarts 安装&#xff1a;npm i echarts --save 二、下载地图json数据 由于echarts内部不再支持地图数据&#xff0c;所以要绘制地图需要自己去下载数据。建议使用阿里云的。 地址&…

接口自动化框架搭建(四):pytest的使用

1&#xff0c;使用说明 网上资料比较多&#xff0c;我这边就简单写下 1&#xff0c;目录结构 2&#xff0c;test_1.py创建两条测试用例 def test_1():print(test1)def test_2():print(test2)3&#xff0c;在pycharm中执行 4&#xff0c;执行结果&#xff1a; 2&#xff0…

Mysql连接报错:1130-host ... is not allowed to connect to this MySql server如何处理

我用navicat连接我的阿里云服务器的mysql服务器的时候,出现了1130的报错。&#xff08;mysql Server version: 5.7.42-0ubuntu0.18.04.1 (Ubuntu)&#xff09; 我来记录一下这个原因&#xff0c;以及修改过程&#xff01; 1.首先进入mysql -u root -p&#xff0c; mysql客户端…

车载电子与软件架构

车载电子与软件架构 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师 (Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝完再挣扎,出门靠自己,四…

Unity LineRenderer的基本了解

在Unity中&#xff0c;LineRenderer组件用于在场景中绘制简单的线条。它通常用于绘制轨迹、路径、激光等效果。 下面来了解下它的基本信息。 1、创建 法1&#xff1a;通过代码创建 using UnityEngine;public class CreateLineRenderer : MonoBehaviour {void Start(){// 创…

排序算法超详细代码和知识点整理(java版)

排序 1、冒泡排序 ​ 两层循环&#xff0c;相邻两个进行比较&#xff0c;大的推到后面去&#xff0c;一共比较“数组长度”轮&#xff0c;每一轮都是从第一个元素开始比较&#xff0c;每一轮比较都会将一个元素固定到数组最后的一个位置。【其实就是不停的把元素往后堆&#…

LLaMA-Factory参数的解答

打开LLaMA-Factory的web页面会有一堆参数 &#xff0c;但不知道怎么选&#xff0c;选哪个&#xff0c;这个文章详细解读一下&#xff0c;每个参数到底是什么含义这是个人写的参数解读&#xff0c;我并非该领域的人如果那个大佬看到有参数不对请反馈一下&#xff0c;或者有补充的…

我于窗中窥月光,恰如仰头见“链表”(Java篇)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

时序预测 | Matlab实现GWO-BP灰狼算法优化BP神经网络时间序列预测

时序预测 | Matlab实现GWO-BP灰狼算法优化BP神经网络时间序列预测 目录 时序预测 | Matlab实现GWO-BP灰狼算法优化BP神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现GWO-BP灰狼算法优化BP神经网络时间序列预测&#xff08;完整源码和数据…

算法学习——LeetCode力扣动态规划篇6

算法学习——LeetCode力扣动态规划篇6 121. 买卖股票的最佳时机 121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09; 描述 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&…

三元组数据模型:构建知识图谱的基石

目录 前言1. 三元组数据模型概述1.1 定义与结构1.2 特点 2. 三元组在知识图谱中的应用2.1 知识表示2.2 知识推理2.3 数据整合 3 三元组的数据格式3.1 N-Triples &#xff1a;3.2 RDF/XML &#xff1a;3.3 Turtle &#xff08;又称为 Terse RDF Triple Language&#xff09;&…

编程语言|C语言——数组与指针

一、数组 同一类型的变量——元素&#xff08;element&#xff09;集中在一起&#xff0c;在内存上排列成一条直线&#xff0c;这就是数组&#xff08;array&#xff09;。 1.1 一维数组 一维数组的声明 int arr1[10]; int arr2[2 8];#define N 10 int arr3[N];int count 10;…

JavaScript的学习笔记

<script src"index.js" defer></script>&#xff0c;defer的作用是延迟加载index.js文件 定义变量 变量的类型分为两大类&#xff1a;基本类型和复合类型 JavaScript是一种弱类型语言&#xff0c;所以没有强类型语言所具有的int,float,char等等&#x…

无药可医还能怎么办?越没本事的人,越喜欢从别人身上找原因!——早读(逆天打工人爬取热门微信文章解读)

无药可医的病该怎么办呢&#xff1f; 引言Python 代码第一篇 洞见 《骆驼祥子》&#xff1a;越没本事的人&#xff0c;越喜欢从别人身上找原因第二篇 人民日报 来啦 新闻早班车要闻社会政策 结尾 “吾日三省吾身&#xff0c;而后深知自助者天助之。” 在人生的迷宫中 遭遇困境时…

域环境共享文件夹,容量配额管理

首先&#xff0c;我们先创建一个新的磁盘&#xff0c;必须在服务器关机的状态下创建&#xff0c;只有在关机状态下才能创建NVMe类型的磁盘。 打开此电脑&#xff0c;右击创建的磁盘&#xff0c;点击属性。 点击共享&#xff0c;点击高级共享。 将共享此文件夹勾选上&#xff0c…

蓝桥杯 第2945题 课程抢购 C++ Java Python

目录 题目 思路和解题方法 c 代码 Java 版本&#xff08;仅供参考&#xff09; Python 版本&#xff08;仅供参考&#xff09; 代码细节&#xff1a; C 代码细节解释: Python 代码细节解释: lenyan算法笔记 语雀 《lenyan算法笔记》 个人笔记日常更新。含金量不高。/…