• C高级day5(Makefile)


    一、Xmind整理:

    二、上课笔记整理:

    1.#----->把带参宏的参数替换成字符串

    1. #include
    2. #include
    3. #include
    4. #define MAX(a,b) a>b?a:b
    5. #define STR(n) #n
    6. int main(int argc, const char *argv[])
    7. {
    8. printf("%d\n",MAX(12,3));
    9. printf("%s\n",STR(hello)); //可以输出hello
    10. return 0;
    11. }

    2.宏替换

    1. #include
    2. #include
    3. #include
    4. #define MAX(a,b) a>b?a:b
    5. #define STR(n) #n
    6. #define N 10
    7. #define M N+10/3
    8. #define NUM N*M+4/M
    9. int main(int argc, const char *argv[])
    10. {
    11. printf("%d\n",MAX(12,3));
    12. printf("%s\n",STR(hello)); //可以输出hello
    13. printf("%d\n",NUM); //106
    14. return 0;
    15. }

    3.##----->实现字符串的拼接

    1. #include
    2. #define unit32_t unsigned int
    3. #define TYPE(a,b) a##b //参数a会和参数b连接到一起
    4. int main(int argc, const char *argv[])
    5. {
    6. unit32_t i; //定义了一个无符号的整形变量i
    7. //TYPE(a,b) --->unit32_t
    8. TYPE(unit,32_t) j; //定义了一个无符号的整形变量j
    9. return 0;
    10. }

    4.宏函数练习

    1. #include
    2. #include
    3. #include
    4. //求最大值的宏函数
    5. #define Max(a,b) {int ret; \
    6. if(a>b) \
    7. printf("%d\n",a); \
    8. else \
    9. printf("%d\n",b);\
    10. }
    11. #define MAX(a,b) ({int ret; \
    12. if(a>b) \
    13. ret=a; \
    14. else \
    15. ret=b;\
    16. ret;\
    17. 100000;\
    18. })
    19. int main(int argc, const char *argv[])
    20. {
    21. Max(90,100);
    22. printf("%d\n",MAX(20,10));
    23. return 0;
    24. }

    5.使用宏函数,求两数的和,写两种:

    a.直接在宏函数中输出结果

    b.返回两数相加后的结果,在主函数内使用变量接收,并输出

    1. #include
    2. #include
    3. #include
    4. #define ADD(a,b) { printf("%d\n",a+b);}
    5. #define Add(a,b) ({ int ret=a+b; ret;})
    6. int main(int argc, const char *argv[])
    7. {
    8. ADD(90,10);
    9. printf("%d\n",Add(100,10));
    10. return 0;
    11. }

    6.第一版Makefile

    1. #表示Makefile中的注释
    2. #这是一个Makefile文件
    3. all:fun #仅描述了,all这个目标需要依赖于fun文件
    4. #all为了保证一定能生成一个可执行文件
    5. fun:fun.o main.o
    6. gcc fun.o main.o -o fun
    7. fun.o:fun.c
    8. gcc -c fun.c -o fun.o
    9. main.o:main.c
    10. gcc -c main.c -o main.o
    11. clean:
    12. rm *.o fun

    7.第二版Makefile ------>引入变量

    1. 变量的赋值方式
    2. =:递归赋值,获取变量最后一次出现的值
    3. +=:追加赋值,把新的值拼接到原有值的后面并且加空格
    4. :=:立即赋值,在哪赋值在哪展开
    5. ?=:条件赋值,如果前面没有定义过就赋值否则不赋值
    6. 变量的访问:$变量名 ${变量名} $(变量名)
    递归赋值

    追加赋值

    立即赋值

    条件赋值

    1. EXE=fun #可执行文件
    2. OBJs+=fun.o #所有中间代码文件,由于项目的文件可能会添加或减少,所以OBJs使用追加赋值
    3. OBJs+=main.o
    4. CC=gcc #CC是一个自动变量,不赋值时make工具会自动推出设备所需的编译器
    5. CFLAGs=-c #gcc的编译参数
    6. all:$(EXE)
    7. $(EXE):${OBJs}
    8. $(CC) $(OBJs) -o $(EXE)
    9. fun.o:fun.c
    10. $(CC) $(CFLAGs) fun.c -o fun.o
    11. main.o:main.c
    12. $(CC) $(CFLAGs) main.c -o main.o
    13. clean:
    14. rm $(OBJs) $(EXE)

    8.第三版Makefile

    1. 引入自动变量 ----->针对于一条规则来说的
    2. $@:所有目标
    3. $^:所有依赖
    4. $<:第一个依赖
    5. 引入通配符
    6. *:rm *.o
    7. %:模式匹配----->目标和依赖之间的唯一匹配关系
    8. %.o:%.c
    9. 字符串的模式匹配的流程:
    10. 通过xxx.o匹配到xxx.c字符串
    11. 由第一条规则展开的OBJs:fun.o main.o
    12. 1、先拿到需要的fun.o文件名,通过模式匹配%匹配到fun
    13. 2、%拿到fun后,在%.c位置展开,展开为fun.c
    14. 模式匹配指的是,使用%,通配掉两个字符串中相同的部分,
    15. 如:fun.c和fun.o fun/fun.的位置就可以通过%匹配
    1. EXE=fun #可执行文件
    2. OBJs+=fun.o #所有中间代码文件,由于项目的文件可能会添加或减少,所以OBJs使用追加赋值
    3. OBJs+=main.o
    4. CC=gcc #CC是一个自动变量,不赋值时make工具会自动推出设备所需的编译器
    5. CFLAGs=-c #gcc的编译参数
    6. all:$(EXE)
    7. $(EXE):${OBJs} #指明一条规则的目标和依赖
    8. $(CC) $^ -o $@ #在通过自动变量找到所有的目标和依赖
    9. %.o:%.c
    10. $(CC) $(CFLAGs) $^ -o $@
    11. clean:
    12. rm $(OBJs) $(EXE)

    9.第四版Makefile ---->引入函数

    1. EXE=fun #可执行文件
    2. Files=$(wildcard *.c)
    3. OBJs=$(patsubst %.c,%.o,$(Files))
    4. CC=gcc #CC是一个自动变量,不赋值时make工具会自动推出设备所需的编译器
    5. CFLAGs=-c #gcc的编译参数
    6. all:$(EXE)
    7. $(EXE):${OBJs} #指明一条规则的目标和依赖
    8. $(CC) $^ -o $@ #在通过自动变量找到所有的目标和依赖
    9. %.o:%.c
    10. $(CC) $(CFLAGs) $^ -o $@
    11. clean:
    12. rm $(OBJs) $(EXE)

    10.伪目标

    1. EXE=fun #可执行文件
    2. Files=$(wildcard *.c)
    3. OBJs=$(patsubst %.c,%.o,$(Files))
    4. CC=gcc #CC是一个自动变量,不赋值时make工具会自动推出设备所需的编译器
    5. CFLAGs=-c #gcc的编译参数
    6. all:$(EXE)
    7. $(EXE):${OBJs} #指明一条规则的目标和依赖
    8. $(CC) $^ -o $@ #在通过自动变量找到所有的目标和依赖
    9. %.o:%.c
    10. $(CC) $(CFLAGs) $^ -o $@
    11. .PHONY:clean #.PHONY表示是一个伪目标
    12. #伪目标的作用,不检查文件时间戳,直接执行规则下的指令
    13. clean:
    14. rm $(OBJs) $(EXE)

    11.枚举定义

    1. enum 枚举名
    2. {
    3. 枚举项;
    4. };
    5. //定义了一个枚举的数据类型 使用enum 枚举名定义枚举变量
    6. typedef enum 枚举名
    7. {
    8. 枚举项;
    9. }新的枚举名; ----->后面可以直接使用新的枚举名定义枚举变量

    12.枚举练习

    1、假设屋内有三个LED等,分别是LED_1,LED_2,LED_3,

    每一个led等分别有两种状态,LED_ON,LED_OFF,

    设计程序模拟,灯的初始化,和控制灯状态的函数

    (要求:分别初始化三盏灯,每个灯都有两种状态)

    写两个函数:

    1、led_init(LED ) ---->初始化LED灯的函数,参数是枚举类型

    2、led_con(LED,LED_C) ------>控制灯状态的函数,两个参数,分别是LED灯,LED_C灯的状态、

    1. #include
    2. //定义了一个led灯的枚举类型
    3. typedef enum led
    4. {
    5. LED_1=1,
    6. LED_2,
    7. LED_3,
    8. }LED;
    9. typedef enum led_c
    10. {
    11. LED_OFF,
    12. LED_ON,
    13. }LED_C;
    14. //初始化LED灯的函数
    15. void led_init(LED led)
    16. {
    17. switch(led)
    18. {
    19. case LED_1: //直接使用枚举项对枚举变量判断
    20. printf("初始化了LED_1灯\n");
    21. break;
    22. case LED_2:
    23. printf("初始化了LED_2灯\n");
    24. break;
    25. case LED_3:
    26. printf("初始化了LED_3灯\n");
    27. break;
    28. }
    29. }
    30. //控制灯开关的函数
    31. void led_con(LED led,LED_C c)
    32. {
    33. switch(led)
    34. {
    35. case LED_1: //直接使用枚举项对枚举变量判断
    36. switch(c)
    37. {
    38. case LED_ON:
    39. printf("打开了LED_1灯\n");
    40. break;
    41. case LED_OFF:
    42. printf("关闭了LED_1灯\n");
    43. break;
    44. }
    45. break;
    46. case LED_2:
    47. switch(c)
    48. {
    49. case LED_ON:
    50. printf("打开了LED_2灯\n");
    51. break;
    52. case LED_OFF:
    53. printf("关闭了LED_2灯\n");
    54. break;
    55. }
    56. break;
    57. case LED_3:
    58. switch(c)
    59. {
    60. case LED_ON:
    61. printf("打开了LED_3灯\n");
    62. break;
    63. case LED_OFF:
    64. printf("关闭了LED_3灯\n");
    65. break;
    66. }
    67. }
    68. }
    69. int main(int argc, const char *argv[])
    70. {
    71. LED led = LED_2;
    72. //调用初始化函数时,直接使用枚举项进行传参
    73. led_init(LED_1);
    74. led_init(LED_2);
    75. led_init(LED_3);
    76. //调用控制函数时,通过枚举变量传参,led是哪一个枚举项,就控制哪一盏灯的状态
    77. led_con(led,LED_ON);
    78. led_con(led,LED_OFF);
    79. return 0;
    80. }
  • 相关阅读:
    flutter doctor --android-licenses报错解决方案
    网络安全(黑客)——2024自学
    JVM Native内存泄露的排查分析(64M 问题)
    用户眼中的 tensor、TensorFlow 系统中的 tensor、tensor 高阶用法 DLPack
    时区的坑,别再踩了!
    FreeRTOS_空闲任务
    第1章 电子设计与制作基础
    Mac修改Mysql8.0密码
    常见的积分商城游戏类型有哪些?
    windows 查看防火墙设置命令使用方法
  • 原文地址:https://blog.csdn.net/m0_68542867/article/details/132918043