宏定义是高级语言编译器提供的常用语法,其目的是利用某一标识符标识某个文本字符串。在编写程序时,如果程序中反复地使用某个数据或某段程序片段,就可以考虑将这个数据或程序片段定义为宏,然后每个出现该数据或程序片段的地方用宏名替代,选择宏定义来做的好处是程序简洁,可读性好,而且当需要修改这些相同的程序片段时,只要修改宏定义中的字符串即可,不需要修改多处。

        宏定义命令:define

       优点:方便程序的修改,同时也能提高程序的运行效率。

宏定义一般有两种形式:无参宏定义带参宏定义


无参宏定义

定义形式

#define 标识符 字符串

注意:
        1.宏定义是用宏名来表示一个字符串,在宏展开时以该字符串取代宏名,只是简单的替换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理不作任何检查。只在编译时检查。
        2.宏定义行末不必加分号(除非你的宏内容中需要有分号)。
        3.宏定义必须写在函数之外,作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令

例1:输入圆的半径输出圆的周长和面积

#include <stdio.h>
#define PI 3.14
int main(){int r;printf("输入半径:");scanf("%d",&r);printf("圆的周长为:%.2f,面积为:%.2f",2*PI*r,PI*r*r); return 0;
}

预处理阶段进行宏替换↓:

#include <stdio.h>
int main(){int r;printf("输入半径:");scanf("%d",&r);printf("圆的周长为:%.2f,面积为:%.2f",2*3.14*r,3.14*r*r); return 0;
}

代码输出: 

例2:通过宏定义输出字符串

#include <stdio.h>
#define HELLO "Hello,"
#define WORLD "World!"
int main(){printf(HELLO WORLD);return 0;
}

预处理阶段进行宏替换↓:

#include <stdio.h>
int main(){printf("Hello," "World!");return 0;
}

代码输出:

例3:请问如下代码S1和S2的输出是否相等


#include <stdio.h>
#define S1 3+4
#define S2 (3+4)
int main(){printf("S1:%d\n",S1*5);printf("S2:%d\n",S2*5);return 0;
}

预处理进行宏替换↓(这里就体现出了直接替换并不会因为你的宏先定义就先计算,而是替换后再做后续处理):

#include <stdio.h>
#define S1 3+4
#define S2 (3+4)
int main(){printf("S1:%d\n",3+4*5);printf("S2:%d\n",(3+4)*5);return 0;
}

 代码输出:


带参宏定义

定义形式

#define 宏名(形参表) 字符串

例1:M(3)==N(3)?  M(3+2)==N(3+2)?

#include<stdio.h>
#define  M(y)  ((y)*(y)+3*(y))
#define  N(y)  (y*y+3*y)
int main(){printf("M(3):%d\n",M(3));printf("N(3):%d\n",N(3));printf("M(3+2):%d\n",M(3+2));printf("N(3+2):%d\n",N(3+2));
}

预处理阶段进行宏替换↓(这个例题主要是为了提醒大家如果要用宏定义进行一些计算,最好将参与计算的所有变量都加上括号以防本题中的情况出现):

#include<stdio.h>
#define  M(y)  ((y)*(y)+3*(y))
#define  N(y)  (y*y+3*y)
int main(){printf("M(3):%d\n",((3)*(3)+3*(3)));printf("N(3):%d\n",(3*3+3*3));printf("M(3+2):%d\n",((3+2)*(3+2)+3*(3+2)));printf("N(3+2):%d\n",(3+2*3+2+3*3+2));
}

 代码输出:

例2:通过宏来计算数组中元素个数

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define Size_Array(b) sizeof(b)/sizeof(b[0])
int main(){int i;srand((unsigned)time(NULL));int b[i=rand()%100];printf("随机数为:%d 数组元素个数为:%d",i,Size_Array(b));
}

预处理阶段进行宏替换↓(很经典的面试小题):

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(){int i;srand((unsigned)time(NULL));int b[i=rand()%100];printf("随机数为:%d 数组元素个数为:%d",i,sizeof(b)/sizeof(b[0]));
}

 代码输出:


#和##运算

#运算

用法:

# 运算符的用处就是把符号转化为字符串。例如,如果 a 是一个宏的形参,则替换文本中的 #a 则被系统转化为 “a”。

#include <stdio.h>
#define TO_STR(s) #s
int main(){printf(TO_STR(HelloWorld!));return 0;
}

 代码输出:

##运算

用法:

## 运算符可以用在替换文本中,而它的作用是起到粘合的作用,即将两个符号组合成一个符号。

#include <stdio.h>
#define CONCAT(x,y) x##y
int main(){printf("%d", CONCAT(1,000));return 0;
}

 代码输出:


变参宏

用法:

当要调用printf类似不确定参数格式时可以使用__VA_ARGS__,在宏定义中,形参列表的最后一个参数为省略号“…”,“__VA_ARGS__”就可以被用在替换文本中,来表示“…”代表了什么。

#define PR(...) printf(__VA_ARGS__)     //宏定义
PR("hello\n");                          //宏调用

例:

#include <stdio.h>
#define P(X, ...) printf("get:"#X":"__VA_ARGS__)
int main(){int j=20,i=10;P(10, "j = %d\n", j); P(10, "j = %d i=%d\n", j,i);      return 0;
}

 代码输出:


#ifndef 条件编译

#ifndef 的最主要目的是防止头文件的重复包含和编译。  

c语言中,对同一个变量或者函数进行多次声明不会报错。所以如果.h文件里进行了声明工作,不使用# ifndef宏定义,多个c文件包含同一个.h文件也不会报错。

  然而c++中,#ifdef的作用域只是在单个文件中。所以如果.h文件里定义了全局变量,即使采用#ifdef宏定义,多个.c文件包含同一个.h文件就会出现全局变量重定义的错误。

使用#ifndef可以避免这种错误:

#ifndef x    //先测试x是否被宏定义过
#define xcode1     //如果x没有被宏定义过,定义x,并编译code1
#endif   code2     //如果x已经定义过了则编译code2,跳过code1

适当的使用条件编译和宏定义可以让代码的运行效率更高,特别是在进行大项目的时候当某个数值使用次数较多且修改比较频繁的情况下,宏定义也是比较高效的(当然函数也可以,等有时间写完函数再来比较一下函数和宏的优缺点吧)

C语言宏定义#define相关推荐

  1. [C语言]宏定义#define的使用详解

    一.宏定义定义常量 预定义符号 FILE //进行编译的源文件 LINE //文件当前的行号 DATE //文件被编译的日期 TIME //文件被编译的时间 STDC //如果编译器遵循ANSI C, ...

  2. C语言-宏定义#define的用法

    目录 1 不带参宏定义 2 带参宏定义 3 与字符串有关的用法 3.1 字符串转换 3.2 字符转换 3.3 字符连接 1 不带参宏定义 这种用法是最简单最常见的一种方式,如下: #define PA ...

  3. c语言 #define dpath .exe是什么意思,C语言宏定义#define

    姓名:吕彬 学号:1613014035 [嵌牛导读]#define 宏定义是个演技非常高超的替身演员,但也会经常耍大牌的,所以我们用它要慎之又慎.它可以出现在代码的任何地方,从本行宏定义开始,以后的代 ...

  4. c语言解除宏定义_C语言宏定义 define,及一些陷阱!

    https://m.toutiaocdn.com/group/6584292311289561607/?iid=39362926900&app=news_article&timesta ...

  5. 宏定义 指针 c语言,C语言宏定义讲解(C和指针 笔记)

    关于C语言宏定义#define 最常用的莫过于通过宏定义定义常数了,例如 #define MAX 1000      通过宏定义程序中需要的常量,方便维护被多次引用的变量,并且宏替换在预处理阶段完成, ...

  6. C语言 | 预处理 | 宏定义 | #define | 定义函数

    文章目录 预处理 预处理运算符 宏定义 无参宏定义 带参宏定义 宏定义-定义函数 此文主要介绍宏定义,并在介绍宏定义时举例介绍预处理命令 预处理 参考:C 预处理器 | 菜鸟教程 重要的预处理器指令如 ...

  7. c语言中#39;xd#39;代表什么,关于C语言宏定义的技巧:#39;##39;和#39;###39;

    关于C语言宏定义的技巧:'#'和'##' '#'和'##' '#'和'##'是两个预处理运算符,只能在预处理的过程中使用.在带参数的宏定义中, '#'运算符后面应该跟一个参数,预处理器会把这个参数转换 ...

  8. c int最小值的宏_C语言宏定义的妙用!用完软硬件效率蹭蹭涨!

    1 概述 在工程规模较小,不是很复杂,与硬件结合紧密,要求移植性的时候,可采用宏定义简化编程,增强程序可读性. 当宏作为常量使用时,C程序员习惯在名字中只使用大写字母.但是并没有如何将用于其他目的的宏 ...

  9. 【⚠️阴沟里翻船,这题都做错了!⚠️】C语言宏定义

    前言 快答题!直接上题,10秒之内报出a的值是多少! #include<stdio.h> #define SQR(x) x*x int main() {int a = 10, k = 2, ...

最新文章

  1. Exception in thread main java.lang.IncompatibleClassChangeError: net/sf/cglib/core/DebuggingClassW
  2. 软件包 sun-java6-jdk 没有可供安装的候选者
  3. php在线考试自动批卷_php网络在线考试组卷系统
  4. c# npoi 2.5版本设置字体加粗_巨巨巨巨推荐:SCI翻译神器,大版本更新来了
  5. 敏捷开发方法学及应用
  6. java 银行项目对于金额的面试题_2019年面试题小结
  7. 《ASP.NET Core 高性能系列》致敬伟大的.NET斗士甲骨文
  8. ECCV 2020 Oral | BorderDet : 用边界特征做检测
  9. python创建二维数组的方法_Python创建二维数组的正确姿势
  10. mysql limit分页_MySQL order by limit 分页数据重复问题
  11. 【386天】跃迁之路——程序员高效学习方法论探索系列(实验阶段143-2018.02.26)...
  12. 现代操作系统原理与实践01:操作系统概述
  13. java enum 长度限制_Java中的Enum的使用与分析
  14. android循环滚动textview,Android 循环上下滚动
  15. activiti包含网关
  16. 如何在Windows环境下使用PyCharm开发PySpark
  17. progressDialog 为什么设置了setProgress()方法无反应?
  18. vue 实现12个月的平铺式日历插件
  19. c语言无法定位程序输入点,【求助】无法定位程序输入点PacketGetVersion于动态链接库Packet.dll上...
  20. 永恒之蓝——windows server 2003 漏洞

热门文章

  1. ChatGPT在五大行业应用落地及带来的影响
  2. 空气中的声压级、声功率级、声强级的区别
  3. python复数的作用_python复数
  4. 什么是装箱(boxing)和拆箱(unboxing)?
  5. STC液压伺服控制系统
  6. 华为 中间系统IS-IS协议基础配置
  7. 手把手教你从0开始搭建自己的个人博客
  8. ubuntu12.04 set python2.7 opencv2.4.9
  9. Apple开发者账号更改公司主体
  10. vue3+ts+vite+elementPlus实现文件上传导入excle给后端,并且清空上传文件后的列表,以及formData变成[object FormData]的解决方法