ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

C语言-宏的使用

2020-06-18 13:52:52  阅读:195  来源: 互联网

标签:10 宏值 int C语言 编译 指令 使用 define


目录

预处理指令的特点

  • 1,以#开头
  • 2,预处理指令都是在编译之前执行的
  • 预处理指令后面都是没有分号

C 程序从编写到编译,链接,执行的一个流程

  • 1,新建一个.c 源文件,.c 的文件是c 程序的源文件
  • 2,在.c 的源文件中写上符合 c 语法规范的源代码
    • C语言严格区分大小写
    • 除了字符串常量,其他的地方必须使用英文输入法
  • 3,使用 cc -c 指令去编译源文件
    • 格式:cc -c 源文件名称
    • 编译做的事情
    • a,先执行源文件中的预处理指令,如果有文件包含指令,就将文件的内容拷贝到指令的地方
    • b,检查 .c 文件中的语法是否符合规范
      • 1,如果符合,生成.o 目标文件,就是.c 文件对应的二进制指令
      • 2,如果不符合语法规范,就报错,不会生成.o 的目标文件
  • 4,链接
    • cc xx.o
    • a,为.o 的目标文件添加启动代码
    • b,链接函数,告诉编译器要调用的函数在什么地方,调用的时候,去正确的地方找实现
    • c,链接成功以后,就会生出一个可执行文件,这个文件就是我们程序了

预处理指令的分类

  • 文件包含指令 # include
  • 宏定义:可以将一段 c 代码定义为 1 个标识,使用这个标识就可以使用这段代码
  • 条件编译指令:

宏定义:

  • 他是一个预处理指令,所以他在编译之前执行
  • 作用:
    • 可以为一段 C 代码定义一个标识,如果你要使用这个 c 代码,那么就是用这个标识就可以了
  • 语法:
    • ----#define 宏名 宏值
    • ----#define N 10
  • 如何使用宏
    • 在C 代码中,直接使用宏的名称就可以了
  • 宏的原理是
    • 在预编译的时候,就会执行源文件中的预处理指令,会将 C 代码中使用宏名的地方替换为宏值,
    • 将 C 代码中的宏名替换为宏值的过程就叫做宏替换

在使用宏的时候需要注意的地方

  • 宏值可以是任意的东东(常量,表达式),在定义宏的时候并不会去检查语法,但是替换的时候就会检查语法了
#include <stdio.h>
# define M 10
# define N 10+10+10
int main(int argc, const char * argv[]) {
    int num = M+10;
    printf("M = %i\n",M);
    printf("num = %i\n",num);
    
    // 宏值是整个表达式,而并不是计算的结果
    int num1 = N * 2;
    printf("num1 = %i\n",num1);
    return 0;
}

  • 无论宏值是什么东西,在定义宏的时候不会去检查语法,只有当完成了宏替换的时候才会去检查替换以后是否符合语法规范

  • 如果宏值是一个表达式,宏值并不是这个表达式的结果,而是这个表达式的本身

  • 如果宏值中包括一个变量名,那么在使用这个宏之前必须保证这个变量存在不然就会报错

# define X a+a
int main(int argc, const char * argv[]) {
    int a = 10;
    int num2 = X;
    
    return 0;
}
  • 无法通过赋值符号给宏改值,因为宏根本就不是变量
  • 宏的作用域问题
    • a, 宏可以定义在函数里面也可以定义在函数外面
    • b,从定义宏的地方,后面的所有的地方都可以使用这个宏,跟变量不一样,就算这个宏定义在这个大括号里面,在这个后面也是可以访问的
    • undef 宏名 -->解除宏指令
    • 默认情况下,宏从定义的地方一致到文件结束都可以使用,#undef 宏名可以让指定的宏提前消失
  • 字符串中如果出现了宏名,并不会认为是一个宏,而是认为是字符串的一部分,字符串中并不会出现宏替换
  • 宏的层层替换
    • 宏值当中我们用到了另外一个宏名,那么就会将这个宏值当中的宏名替换为对应的宏值
# define P 3
# define A 5
# define JISUAN P*A

int main(){
    printf("JISUAN = %i\n",JISUAN);
}
  • 如果后面跟了分号,那么就会将分号作为宏值的一部分,但是建议不要这么写
  • C语言的代码都可以用作宏值
# define p printf
# define d "%i"
int main(){
    p(d,10);
    return 0;
}

define 和 typedef 的区别

  • ----#define 是一个预处理指令,在预编译的时候执行,在预编译的时候会把宏名替换为宏值
    • typedef 是一个 C 代码.在运行的时候执行
  • ----#define可以将任意的C 代码取 1 个标识名
    • typedef 只能为数据类型取名字

宏的高级用法

  • 我们在定义宏的时候,宏名是可以带参数的,在这个宏值当中,可以直接使用这个参数
  • 如果使用的宏有参数,那么就必须要在使用它的时候为这个宏的参数传值
# define B(a) a+10+a

int main(){
    // 有参数的宏
    int num3 = B(8);
    printf("num3 = %i\n",num3);
    return 0;
}

image-20200615225818231

  • 宏替换的原理是什么?
    • 先将传入的值传递给宏的参数,那么宏的参数的值就是我们传递的值
    • 再把宏值当中使用参数的地方换成参数的值
    • 最后,再将使用宏名的地方,替换为最后的宏值
# define MAX(a,b) a > b ? a:b
int main(){
    printf("最大值是:%i\n",MAX(10, 0));
    return 0;
}

使用带参数的宏注意点

  • 宏不是函数,所以宏的参数不需要写数据类型,直接写参数名称即可
  • 我们在定义宏的时候,编译器是如何区分宏名和宏值的呢?
    • ----#define空格宏名空格宏值 --->两个空格之间的就是宏名
  • 为带参数的宏传递的时候是本色传递(本色传递:你给的什么,那就是什么,预编译的时候啥都没有就是直接本色的替换)
  • 宏一定程度上可以实现和函数一样的效果
    • 宏一旦换了行就代表宏定义结束了,
    • 代码很少的时候会使用宏,只有一句,两句的时候可以使用宏

条件编译指令

  • 他也是一个预处理指令,所以在预编译阶段执行
  • 作用:默认情况下我们所有的 C 代码都会被编译为二进制代码,条件编译指令的作用:可以让编译器只编译置顶的部分
  • 条件编译指令的一种用法
    • if 条件
    • c 代码
    • endif
# define M 10
int main(){
        // 条件编译指令
#if M == 10
    printf("我是条件编译指令的代码\n");
#endif
    return 0;
}

// 输出:我是条件编译指令的代码
  • 注意:条件只能是宏,不能是变量,因为:预编译的时候变量还没有呢
    int m = 10;
#if m == 10
    printf("我是 变量 m == 10 才会执行的代码\n");
#endif
  • 条件编译指令的第二种用法
# define M 10

int main(){
    #if M > 0
    printf("M>0编译这个代码\n");
#elif M > 0 && M < 20
    printf("M > 0 && M < 20编译这个代码\n");
#elif M >20 && M < 40
    printf("M >20 && M < 40编译这个代码\n");
#else
    printf("否则编译这个代码");
#endif
    
    return 0;
}
  • 条件编译指令和 if 语句的对比
    • 1,条件编译指令是一个预处理指令,在预处理阶段执行,if 语句是 C代码.在程序运行的时候执行
    • 2,if 语句全部都要被编译为二进制指令,条件编译指令只会编译条件符合的代码
    • 3,实际上,if 语句一定程度上可以换成条件编译指令,但是条件编译指令的条件不能是变量参与,只能是宏
  • 条件编译指令的第三种用法,如果定义了指定的宏,就编译指定的代码
#define M 10
int main(){
        // 第三种用法
#if M
    printf("如果定义了这个宏,就执行这个代码\n");
#endif
    return 0;
}
int main(){
        // 第三种用法
#ifndef M
    printf("如果没有定义了这个宏,就执行这个代码\n");
#endif
    return 0;
}

条件编译指令的应用场景

// 在调试的时候,调试信息有很多,又不想每次都一个一个的删除,那么可以使用条件编译指令,每次只需要修改自己定义的宏就可以对 printf 函数的控制

#include <stdio.h>


# define SHAN_DEBUG 0
# if SHAN_DEBUG == 0
    # define print(val1,val2) printf(val1,val2)
# else
    # define print(val1,val2)
# endif


int main(int argc, const char * argv[]) {

    print("%d",10);
    
    
    
    return 0;
}


// 无论一个文件包被#include 多少次,我只引入一次
#ifndef lianxi_h
#define lianxi_h

#include <stdio.h>
 // 写自己的代码
#endif /* lianxi_h */

// 原理:在 main.c中#include lianxi.h,导入很多次,#include 的作用就是将此文件全部复制过来,所以复制第一次在编译的时候如果没有导入 lianxi.h 这个文件,全部被copy 过来,此时没有定义 lianxi.h 这个宏,那么就定义这个宏 lianxi.h,然后在第二次copy 过来的时候,发现定义了这个 lianxi.h 这个宏,所以就不会重复的 copy 了

标签:10,宏值,int,C语言,编译,指令,使用,define
来源: https://www.cnblogs.com/shanshan-test/p/13157147.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有