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

第15天预编译

预编译指令

编译四步

预编译->编译->汇编->链接

预编译:整理代码,检查代码格式问题

C 语言文件分类

运行时是否分配空间

.c C 文件->源文件:存储代码的实体 运行需要空间

.h H 文件->头文件:存储各种声明 声明只是为了告知有什么东西在当前的模块文件.c 中定义

#include 文件包含

  • #include <>  系统库路径下查找
  • #include “” 先在工程路径下查找,再去系统库路径下查找

#include<stdio.h> 预编译阶段,查找到 stdio.h 头文件,并把头文件内容全部复制到当前位置 然后才能在当前文件下方使用 printf();

#if…#else…#endif 条件编译

和 if…else…的用法一致

  • 流程控制语句 if:如果条件成立,则执行代码块
if() {
}
else {
}
  • 预编译指令#if:如果条件成立,则以下代码参与编译
#if 1 //代码 1 
#else //代码 2 
#endif

#if 是开始,#endif 是结束,成对出现

#define 宏定义

#define 宏名 宏内容

展开宏定义,用于定义一个简单的文本替换        [宏展开]

只在预编译阶段进行字符的替换,不进行任何形式的运算和执行

把宏内容替换代码中的宏名

无参宏

#define SIZE 5+4 printf(“%d\n”, SIZE*3);

预编译阶段会替换为:printf(“%d\n”, 5+4*3);

无参宏与 typedef 的区别
#define INT int * 
INT a,b; // int *a,b; // a==8 b==4 typedef INT int *; 
INT a,b; // int *a,*b; // a==8 b==8

在这里,使用 #define INT int * 定义宏,当写下 INT a, b; 时,预编译阶段会展开为 int *a, b; 。这意味着 a 被定义为 int 指针,而 b 只是一个 int 类型的变量。使用 typedef INT int *; 定义了一个新的类型 INT 表示 int 指针类型。当写下 INT a, b; 时,就相当于定义了两个 int 指针 a 和 b 。这种差异是由于 #define 只是简单的文本替换,而 typedef 是真正定义了一个新的数据类型。

  • #define 预处理指令,预编译阶段执行,只是进行字符替换
  • typedef 关键字,程序运行时执行,对类型的重命名

有参宏

#define SIZE(a,b) a+b printf(“%d\n”, SIZE(4,5)*3);

预编译阶段会替换为:printf(“%d\n”, 4+5*3);

有参宏与函数的区别

#define:参数没有类型限制,可以对代码进行封装,但是预编译阶段就会展开,不会减少代码体积,但是能 提升代码执行效率

函数:参数有类型限制,可以对代码进行封装,程序运行时直接调用,可以减少代码体积,但是会降低代码 执行效率

所以在一些底层代码中,尤其是需要执行效率的核心代码,有参宏比较常见 我们在使用时需要注意参数的类型问题

#undef 取消宏定义

#undef 宏名

从当前行开始向下,宏名不在生效,内容取消

  • #if 宏名 判断宏的值是真是假

#ifdef 判断宏是否被定义

#ifdef 宏名

宏存在条件成立

#ifndef 判断宏是否没有定义

#ifndef 宏名

宏不存在条件成立

防止头文件重复包含的用法 头文件中写入以下 3 行格式

#ifndef 宏名

#define 宏名

#endif

#ifndef MYHEADER_H
#define MYHEADER_H// 头文件的具体内容,比如函数声明、结构体定义等#endif

当这个头文件被包含时,如果之前没有定义过 MYHEADER_H 这个宏,那么就会执行中间的代码。如果已经定义过了,说明是重复包含,中间的代码就会被忽略,从而避免了重复定义和声明带来的问题。

宏的名称通常使用头文件名全大写并加上 _H 的格式,但也可以根据您的项目约定进行修改,只要保证唯一性即可。

模块化

把代码进行模块化封装

把整体的项目进行拆分,分成多个模块文件,进行调用

项目中一定要有一个 main.c 文件,编写主函数 main

其他的模块文件,要一个 C 对应一个 H,但是 H 也可以是多个文件

模块化操作练习

第一个模块:运算两个整数的加法,并把结果通过返回值输出 int add_t(int a,int b)

第二个模块:运算两个整数的减法,运算结果保存到全局变量 int X; void sub_t(int a,int b)

第三个模块:运算两个整数的乘法,使用的数据采用结构体形式传递 struct A{ int a; int b; int Y; }; void mul_t(struct A *p)

第四个模块:运算两个整数的加法,利用有参宏代替函数 主函数调用模块实现操作

成果示例:

main.c

#include <stdio.h>
#include "He.h"
#include "cha.h"
#include "ji.h"
#include "hong.h"
int main(){
int resu=0;
resu=He(1,2);
printf("%d\n",resu);cha(5,3);
printf("%d\n",X);struct A num={12,4,0};
ji(&num);
printf("%d\n",num.Y);resu=SIZE(2+4,5);
printf("%d\n",resu);return 0;
}

He.c 

int He(int a,int b){
return a+b;
}

 He.h

#ifndef _HE_H_
#define _HE_H_int He(int a,int b);#endif

cha.c

#include "cha.h"
int X;
void cha(int a,int b){X=a-b;
}

cha.h 

#ifndef _CHA_H_
#define _CHA_H_
extern int X;
void cha(int a,int b);#endif

ji.c

#include "ji.h"
void ji(struct A *p){
p->Y=p->a*p->b;
}

ji.h

#ifndef _JI_H_
#define _JI_H_struct A{
int a;
int b;
int Y;
};void ji(struct A *p);#endif

hong.c

#include "hong.h"

hong.h

#ifndef _HONG_H_
#define _HONG_H_#define SIZE(a,b) (a+b)#endif

多模块编译操作

Linux:gcc *.c -o main


http://www.mrgr.cn/news/62363.html

相关文章:

  • GraphQL系列 - 第1讲 GraphQL语法入门
  • qt QDialog详解
  • ffmpeg+vue2
  • Spring Boot框架下的信息学科平台系统架构设计
  • kafka消费者组分区分配实战
  • HarmonyOS-权限管理
  • 组合两个表
  • 计算机组成原理之选择结构语句的机器级别表示
  • HTTPS对中间人真就束手就擒了?
  • NFT、加密货币和区块链将如何在某一天共同推动Web3
  • 基于 ThinkPHP+Mysql灵活用工_灵活用工系统_灵活用工平台
  • 什么样的工程项目管理软件适合中小施工企业?
  • 最小期望风险估计
  • Python中的命名规则是什么?
  • 2020年下半年网络规划设计师上午真题及答案解析
  • 前端如何检测用户登录状态是否过期?
  • 跟着小土堆学习pytorch(六)——神经网络的基本骨架(nn.model)
  • 百度搜索引擎的工作原理
  • linux下的进程,fork、exec函数族简介
  • 如何查看磁盘的类型?(固态硬盘 or 机械硬盘)
  • 【大模型之Graph RAG系列之一】由谷歌搜索的演进看知识图谱如何改进RAG技术
  • 《云计算网络技术与应用》实训8-1:OpenvSwitch简单配置练习
  • 百度集度嵌入式面试题及参考答案
  • JS实现图片放大镜效果
  • 我docker拉取mysql镜像时用的是latest,我该怎么看我的镜像版本是多少?可以通过一下三种方法查看
  • 用Python下载指定URL的图片并保存到本地