当前位置 博文首页 > CW_qian的博客:8月22日笔记C语言基础(补3)宏定义与条件编译2

    CW_qian的博客:8月22日笔记C语言基础(补3)宏定义与条件编译2

    作者:[db:作者] 时间:2021-08-25 21:43

    1.预处理
    ?? ?程序在编译之前,是由预处理器CC1先检查c文件有没有以#号开头的符号称为宏
    ?? ?如果有,CC1是不会做任何的逻辑判断直接将里里面的内容替换出来,或者拷贝出来
    ?? ?我们把这种方式称为宏展开
    ?? ?
    预处理指令(宏)包括
    ?? ?1.头文件 #include?
    ?? ?2.定义宏 #define
    ?? ?3.取消 #undef
    ?? ?4.条件编译 #if #ifdef #ifndef #else #elif #endif
    ?? ?5.向编译器发送指令 #pragma
    ?? ??? ?#pragma pack(1) // 设置结构体M值的大小
    ?? ??? ?加载库
    ?? ??? ?


    2.宏的概念
    ?? ?宏其实就是一段特定的字符串,在预处理的时候会被替换
    ?? ?
    3.宏的分类
    ?? ?1.无参宏之自定义宏
    ?? ??? ?无参宏的意思是使用的时候无需指定任何的参数
    ?? ?例如:?
    ?? ??? ?#define PI 3.14
    ?? ??? ?#define LCD_SIZE 800*480*4
    ?? ??? ?
    ?? ?注意:此处的PI表示宏,一般使用大写字母表示,用于区分变量和函数,当然这不是
    ?? ??? ?语法规定,只是个人习惯而已
    ?? ??? ?
    ?? ?2.无参宏之系统宏
    ?? ??? ?#define O_RDONLY : 0x1?
    ?? ??? ?#define O_WRONLY : 0X2
    ?? ??? ?#define NULL ((void *)0) char *p = NULL 等价于 char *p = (void *)0;
    ?? ??? ?
    ?? ?3.带参宏
    ?? ??? ?带参宏意味着宏定义是可以带参数的,从形式上看是和函数很像
    ?? ??? ?
    ?? ??? ?#define MAX(a,b) a>b ? a : b?
    ?? ??? ?#define MIN(a,b) a<b ? a : b?
    ?? ??? ?
    ?? ?4.带参数的宏的特点:
    ?? ??? ?1.直接文本替换,不做任何的语法判断,不做任何的中间转换
    ?? ??? ?2.宏在预编译的时候已经被替换了,所以运行的时候不存在宏
    ?? ??? ?3.宏展开的时候浪费了内存空间,但是节约了程序运行的时间
    ?? ??? ?
    ?? ?5.带参宏的问题解决方式:
    ?? ??? ?//#define MAX(a,b) a>b ? a : b // 容易出bug 解决方法如下
    ?? ??? ?#define MAX(a,b) ((a)>(b) ? (a) : (b))
    ?? ?
    ?? ?6.无值的宏
    ?? ??? ?#define _MYHEAD_H
    ?? ??? ?#define WIN_32
    ?? ??? ?#define WIN_64
    ?? ??? ?
    ?? ??? ?无值宏一般是头文件或者在编译中作为判断条件出现
    ?? ??? ?
    ?? ?7.总结
    ?? ??? ?1.宏是用于替换指定的表达式,增加代码的可读性
    ?? ??? ?2.使得程序修改比较方便,如果程序有多个地方使用到宏的时候,只需要修改宏定义即可
    ?? ??? ?3.提高程序的运行效率


    2.条件编译
    ?? ?是用来控制编译器编译哪一段代码
    ?? ?#if? ? ? ? ? ? ? ? 如果条件为真,则执行相应的操作,可以起到类似于注释的效果
    ?? ?#elif? ? ? ? ? ? ?如果前面的为假,那么执行此语句
    ?? ?#else? ? ? ? ? ?如果前面的操作都为假,则执行以下语句
    ?? ?#endif? ? ? ? ? 结束条件编译
    ?? ?#ifdef? ? ? ? ? ?如果改宏已经被定义则执行相应的操作
    ?? ?#ifndef ????????如果宏没被定义,则执行相应的操作
    ?? ?
    ?? ?#if -- #else -- #endif
    ?? ?格式如下:
    ?? ?#if 条件表达式
    ?? ??? ?代码段1
    ?? ?#else
    ?? ??? ?代码段2
    ?? ?#endif
    ?? ?demo:

    ? ??? ?#define DEBUG 1

    ?? ??? ?int main()
    ?? ??? ?{
    ?? ??? ??? ?#if 0 // 0 为假
    ?? ??? ??? ??? ?printf("此处为假\n");
    ?? ??? ??? ?#else
    ?? ??? ??? ??? ?printf("此处为真\n");
    ?? ??? ??? ?#endif
    ?? ??? ??? ?
    ?? ??? ??? ?#if DEBUG //DEBUG 为真
    ?? ??? ??? ??? ?printf("此处为真\n");
    ?? ??? ??? ?#else
    ?? ??? ??? ??? ?printf("此处为假\n");
    ?? ??? ??? ?#endif // 结束
    ?? ??? ??? ?return 0;
    ?? ??? ?}


    ? 条件编译,多路分支
    ?? ?#if -- #elif -- #elif -- #endif
    ?? ?#define A 1
    ?? ?#define B 2
    ?? ?#define C 3
    ?? ?//-----------------
    ?? ?#if A
    ?? ??? ?printf("A\n");
    ?? ?#elif B
    ?? ??? ?printf("A\n");
    ?? ?#elif C
    ?? ??? ?printf("A\n");
    ?? ?#endif?? ?
    ??


    ? ? 检测程序中如果没有定义宏则定义
    ?? ?#ifndef --- #define --- #endif
    ?? ?定义格式
    ?? ??? ?#ifndef 标识符
    ?? ??? ?#define 标识符 替换列表
    ?? ??? ?#endif
    ?? ?demo:

    ?? ??? ?#define PI 3.1415
    ?? ??? ?#ifndef PI
    ?? ??? ?#define PI 3.14
    ?? ??? ?#endif

    ? ?运用场景主要是头文件


    ? ? 检测如果定义了宏则删除
    ?? ?#ifdef -- #undef -- #endif
    ?? ?定义格式:
    ?? ??? ?#ifdef 标识符
    ?? ??? ??? ?代码段1
    ?? ??? ?#endif
    ?? ?demo:

    ?? ??? ?#define N 456
    ?? ??? ?#ifdef N
    ?? ??? ?#undef N
    ?? ??? ?#define N 123
    ?? ??? ?#endif


    ? ?条件编译的使用场景
    ?? ?在程序中,用条件编译将调试语句包裹起来,通过gcc编译器来选择编译哪一段
    ?? ?代码
    ?? ?int main()
    ?? ?{
    ?? ??? ?#ifdef A // 现在没有定义此宏
    ?? ??? ??? ?printf("A\n");
    ?? ??? ?#else
    ?? ??? ??? ?printf("haha\n");
    ?? ??? ?#endif
    ?? ??? ?
    ?? ?}
    ?? ?编译方法:
    ?? ??? ?gcc main.c -o main -DA // -D 的意思是编译程序的时候定义哪一个宏
    ?? ??? ?
    作业:

    ?? ?现有一个嵌入式设备终端传输过来的数据包是一个32位无符号的整型数,这个数据包里面各位含义如下:
    ?? ?00-07位:表示温度数据
    ?? ?08-15位:表示湿度数据
    ?? ?16-19位:表示4扇门状态(门的编号0-3) ? ? ?二进制:0001 ?0010 0100 1000 ? 十六进制 1 2 4 8
    ?? ?20-23位:表示四盏灯的状态(灯编号0-3)
    ?? ?24-31位:预留备用
    ?? ?下面是最近一段时间接受的数据包:
    ?? ?0x12344520, 0xff004B1C,0x00553C1E
    ?? ?请编写一个程序接收这3个数据包,并解析出对应的数据【温度,湿度,门0-3,灯0-3】(门和灯的状态0-关,1-开)。
    ?? ?
    ?? ?使用宏来实现以上功能:
    ?? ?提示

    ?? ?#define TEMP_MASK 0x000000FF
    ?? ?#define HUMI_MASK 0x0000FF00
    ?? ?

    ?? ?#include <stdio.h>
    ?? ?#define TEMP_MASK 0x000000FF
    ?? ?#define HUMI_MASK 0x0000FF00
    ?? ?
    ?? ?#define TEMPERATURE(a) ((a&TEMP_MASK) >> 0)
    ?? ?#define HUMIDITY(a) ?((a&HUMI_MASK) >> 8)
    ?? ??? ?
    ?? ?#define DOOR0_MASK 0x00010000
    ?? ?#define DOOR1_MASK 0x00020000
    ?? ?#define DOOR2_MASK 0x00040000
    ?? ?#define DOOR3_MASK 0x00080000
    ?? ?
    ?? ?#define LIGHT0_MASK 0x00100000
    ?? ?#define LIGHT1_MASK 0x00200000
    ?? ?#define LIGHT2_MASK 0x00400000
    ?? ?#define LIGHT3_MASK 0x00800000
    ?? ?
    ?? ?int main()
    ?? ?{
    ?? ??? ?unsigned int data;
    ?? ??? ?printf("请输入接收到的数据:\n");
    ?? ??? ?while(1)
    ?? ??? ?{
    ?? ??? ??? ?scanf("%x",data);
    ?? ??? ??? ?
    ?? ??? ??? ?printf("温度: ?%d\n",TEMPERATURE(data));
    ?? ??? ??? ?printf("湿度: ?%d\n",TEMPERATURE(HUMIDITY));
    ?? ??? ??? ?
    ?? ??? ??? ?printf("门0: %s\t",(data & DOOR0_MASK) ? "开":"关");
    ?? ??? ??? ?printf("门1: %s\t",(data & DOOR1_MASK) ? "开":"关");
    ?? ??? ??? ?printf("门2: %s\t",(data & DOOR2_MASK) ? "开":"关");
    ?? ??? ??? ?printf("门3: %s\t",(data & DOOR3_MASK) ? "开":"关");
    ?? ??? ??? ?
    ?? ??? ??? ?printf("灯0: %s\t",(data & LIGHT0_MASK) ? "亮":"灭");
    ?? ??? ??? ?printf("灯1: %s\t",(data & LIGHT1_MASK) ? "亮":"灭");
    ?? ??? ??? ?printf("灯2: %s\t",(data & LIGHT2_MASK) ? "亮":"灭");
    ?? ??? ??? ?printf("灯3: %s\t",(data & LIGHT3_MASK) ? "亮":"灭");
    ?? ??? ??? ?
    ?? ??? ?}
    ?? ??? ?
    ?? ?}


    cs