第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