C语言-编译和链接

news2024/11/26 0:23:14

目录

    • 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.链接

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电商系列之取消订单

> 插&#xff1a;AI时代&#xff0c;程序员或多或少要了解些人工智能&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家…

每日面经分享(Spring Boot: part2 DAO层)

1. Spring Boot DAO层的作用 a. 封装数据访问逻辑&#xff1a;DAO层的主要责任是封装与数据访问相关的逻辑。负责处理与数据库的交互&#xff0c;包括数据的增删改查等操作。通过将数据访问逻辑统一封装在DAO层中&#xff0c;可以提高代码的可维护性和可重用性。 b. 解耦业务逻…

java Web 疫苗预约管理系统用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP 疫苗预约管理系统是一套完善的web设计系统&#xff0c;对理解JSP java 编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0&#xff0c;使…

蓝桥集训之游戏

蓝桥集训之游戏 核心思想&#xff1a;博弈论 区间dp 设玩家1的最优解为A 玩家2的最优解为B 1的目标就是使A-B最大 2的目标就是使B-A最大 当玩家1取L左端点时 右边子区间结果就是玩家2的最优解B-A 即当前结果为w[L] – (B-A) 当玩家1取R右端点时 左边子区间结果就是玩家2的最…

<TensorFlow学习使用P1>——《TensorFlow教程》

一、TensorFlow概述 前言&#xff1a; 本文中一些TensorFlow综合案例的代码逻辑一般正常&#xff0c;在本地均可运行。如有代码复现运行失败&#xff0c;原因如下&#xff1a; &#xff08;1&#xff09;运行环境配置可能有误。 &#xff08;2&#xff09;由于一些数据集存储空…

算法学习——LeetCode力扣图论篇2

算法学习——LeetCode力扣图论篇2 1020. 飞地的数量 1020. 飞地的数量 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个大小为 m x n 的二进制矩阵 grid &#xff0c;其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相…

实施阶段(2024年3月)

本次探究的项目化学习主题为&#xff1a;校内订餐系统的分析与设计 【主题情境说明】 社会大背景&#xff1a;国家颁发《“健康中国2030”规划纲要》&#xff0c;尤其关注青少年儿童膳食质量&#xff0c;明确提出要加强孩子食育教育&#xff0c;家庭、学校和社会需要共建健康…

Linux系统---如何理解Linux中的文件系统

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、理解文件系统 1.ls与stat 我们使用ls -l的时候看到的除了看到文件名&#xff0c;还看到了文件元数据。 每行包含7列…

【一站式学会Kotlin】第一节 kotlin 介绍

作者介绍&#xff1a; 百度资深Android工程师T6&#xff0c;在百度任职7年半。 目前&#xff1a;成立赵小灰代码工作室&#xff0c;欢迎大家找我开发Android、微信小程序、鸿蒙项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默。给大家…

Unity 基于Rigidbody2D模块的角色移动

制作好站立和移动的动画后 控制器设计 站立 移动 角色移动代码如下&#xff1a; using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine;public class p1_c : MonoBehaviour {// 获取动画组件private Animator …

【c++】简单的日期计算器

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好啊&#xff0c;在我们学习了默认成员函数后&#xff0c;我们本节内容来完成知识的实践&#xff0c;来实现一个简易的日期计算器 目录 头文件声明函数函数的实现1.全缺省默认构…

TASKPROMPTER

baseline模型的预训练权重就有1.6G! 多吓人呐&#xff0c;当时我就暂停下载了&#xff0c;不建议复现

[Flutter]打包IPA

1.直接使用Xcode运行iOS工程 不用flutter构建&#xff0c;在Xcode中是可以独立进行构建运行和打包发布的。 1).运行项目 先将flutter的build清理 $ flutter clean $ flutter pub get 然后立即用XCode打开iOS工程运行 运行会报错&#xff1a; error: The sandbox is not …

gpt-llm-trainer 出炉

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

ML-Decoder: Scalable and Versatile Classification Head

1、引言 论文链接&#xff1a;https://openaccess.thecvf.com/content/WACV2023/papers/Ridnik_ML-Decoder_Scalable_and_Versatile_Classification_Head_WACV_2023_paper.pdf 因为 transformer 解码器分类头[1] 在少类别多标签分类数据集上表现得很好&#xff0c;但由于其查询…

【应用层协议原理】

文章目录 第二章 应用层2.1 应用层协议原理2.1.1 网络应用的体系结构2.1.2 客户-服务器&#xff08;C/S&#xff09;体系结构2.1.3 对等体&#xff08;P2P&#xff09;体系结构2.2.4 C/S和P2P体系结构的混合体2.2.5 进程通信问题1&#xff1a;对进程进行编址&#xff08;addres…

厦门攸信技术亮相新技术研讨会,展现物流自动化解决方案新高度!

今日&#xff0c;厦门攸信信息技术有限公司受邀参加了一场备受行业关注的电子制造高端盛会——一步步新技术研讨会&#xff0c;凭借卓越的智能制造与物流自动化技术在会议中大放异彩。作为一家引领行业发展的企业&#xff0c;厦门攸信技术不仅展示了其深厚的技术底蕴&#xff0…

算法之美:堆排序原理剖析及应用案例分解实现

这段时间持续更新关于“二叉树”的专栏文章&#xff0c;关心的小伙伴们对于二叉树的基本原理已经有了初步的了解。接下来&#xff0c;我将会更深入地探究二叉树的原理&#xff0c;并且展示如何将这些原理应用到更广泛的场景中去。文章将延续前面文章的风格&#xff0c;尽量精炼…

数据结构 - 图

参考链接&#xff1a;数据结构&#xff1a;图(Graph)【详解】_图数据结构-CSDN博客 图的定义 图(Graph)是由顶点的有穷非空集合 V ( G ) 和顶点之间边的集合 E ( G ) 组成&#xff0c;通常表示为: G ( V , E ) &#xff0c;其中&#xff0c; G 表示个图&#xff0c; V 是图 G…

深入理解 Hadoop 上的 Hive 查询执行流程

在 Hadoop 生态系统中&#xff0c;Hive 是一个重要的分支&#xff0c;它构建在 Hadoop 之上&#xff0c;提供了一个开源的数据仓库系统。它的主要功能是查询和分析存储在 Hadoop 文件中的大型数据集&#xff0c;包括结构化和半结构化数据。Hive 在数据查询、分析和汇总方面发挥…