c语言 宏定义 宏用法
目录
#define 标识符 常量
1.#if系列用法
2.#ifdef用法
3.#ifndef用法
4.#error用法
#define 标识符 常量
C语言中,可以用 #define 定义一个标识符来表示一个常量。其特点是:定义的标识符不占内存,只是一个临时的符号,预编译后这个符号就不存在了。
预编译又叫预处理。预编译不是编译,而是编译前的处理。这个操作是在正式编译之前由系统自动完成的。
用 #define 定义标识符的一般形式为:
#define 标识符 常量 //注意, 最后没有分号
#define 和 #include 一样,也是以“#”开头的。凡是以“#”开头的均为预处理指令,#define也不例外。
#define又称宏定义,标识符为所定义的宏名,简称宏。标识符的命名规则与前面讲的变量的命名规则是一样的。#define 的功能是将标识符定义为其后的常量。一经定义,程序中就可以直接用标识符来表示这个常量。是不是与定义变量类似?但是要区分开!变量名表示的是一个变量,但宏名表示的是一个常量。可以给变量赋值,但绝不能给常量赋值。
宏所表示的常量可以是数字、字符、字符串、表达式。其中最常用的是数字。
那么,程序中什么时候会使用宏定义呢?用宏定义有什么好处呢?我们直接写数字不行吗?为什么要用一个标识符表示数字呢?
宏定义最大的好处是“方便程序的修改”。使用宏定义可以用宏代替一个在程序中经常使用的常量。注意,是“经常”使用的。这样,当需要改变这个常量的值时,就不需要对整个程序一个一个进行修改,只需修改宏定义中的常量即可。且当常量比较长时,使用宏就可以用较短的有意义的标识符来代替它,这样编程的时候就会更方便,不容易出错。因此,宏定义的优点就是方便和易于维护。
那么程序在预编译的时候是怎么处理宏定义的呢?或者说是怎么处理预处理指令的呢?
其实预编译所执行的操作就是简单的“文本”替换。对宏定义而言,预编译的时候会将程序中所有出现“标识符”的地方全部用这个“常量”替换,称为“宏替换”或“宏展开”。替换完了之后再进行正式的编译。所以说当单击“编译”的时候实际上是执行了两个操作,即先预编译,然后才正式编译。#include<stdio.h>也是这样的,即在预处理的时候先单纯地用头文件stdio.h中所有的“文本”内容替换程序中#include<stdio.h>这一行,然后再进行正式编译。
需要注意的是,预处理指令不是语句,所以后面不能加分号。这是很多新手经常犯的错误。#include 后面也没有加分号。
宏定义 #define 一般都写在函数外面,与 #include 写在一起。当然,写在函数里面也没有语法错误,但通常不那么写。#define 的作用域为自 #define 那一行起到源程序结束。如果要终止其作用域可以使用 #undef 命令,格式为:
#undef 标识符
undef 后面的标识符表示你所要终止的宏。比如前面在程序开头用 define 定义了一个宏 M,它原本的作用范围是一直到程序结束,但如果现在在程序中某个位置加了一句:
#undef M
那么这个宏的作用范围到此就结束了。#undef 用得不多,但大家要了解。
为了将标识符与变量名区别开来,习惯上标识符全部用大写字母表示。宏定义用得最多的地方是在数组中用于指定数组的长度。下面来写一个程序:
# include <stdio.h># define NUM 5int main(void){int i, j = NUM;int a[NUM] = {0};printf("请输入%d个数:", j);for (i=0; i<NUM; ++i){scanf("%d", &a[i] );}for (i=0; i<NUM; ++i){printf("%d\x20", a[i]);}printf("\n");return 0;}
输出结果是:
请输入5个数:5 4 3 2 1
5 4 3 2 1
NUM 是定义的宏,它表示的是其后的常量(而不是变量)。此外,程序中用双引号括起来的宏在预处理的时候是不会被宏替换的。因为在 C 语言中,用双引号括起来表示的是字符串。下面再写一个程序看一下:
# include <stdio.h># define PI 3.14159int main(void){double r, s;printf("请输入圆的半径:");scanf("%lf", &r); //scanf中, double只能用%lfs = PI * r * r;printf("s=PI*r^2 = %.6f\n", s); //PI不会被宏替换return 0;}
输出结果是:
请输入圆的半径:1
s=PI*r^2 = 3.141590
宏在C++或者C编程中,由于宏支持较早,使用非常广泛。下文详细分析每种宏的用法
1.#if系列用法
常量表达式非0时,程序段参加编译;为0时,程序段不参加编译
#if 常量表达式程序段
#endif
if后为真编译第一段,elif后为真编译第二段,都为假编译第三段
#if 常量表达式程序段1
#elif 常量表达式程序段2
#else程序段3
#endif
2.#ifdef用法
标识符已经是一个定义过的宏名,则程序段参加编译,否则调用另外一段,#else段可选。
#ifdef 标识符程序段
#else程序段
#endif
3.#ifndef用法
标识符没定义过,则程序段参加编译,否则调用另外一段,#else段可选。
#ifndef 标识符程序段
#else程序段
#endif
4.#error用法
用于发现错误,在错误的那一行会跳出编译过程。
#error后面只是一个人为提示的字符串,请自行定义。
————————————————
版权声明:本文为CSDN博主「插件开发」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_67316550/article/details/124358636
c语言 宏定义 宏用法相关推荐
- C语言中#、##宏定义的用法
一.#的用法 #用于编译器编译过程进行预处理. 1.宏定义 #define ON 1#ifndef _PARA_ #define _PARA_ #enddef#ifdef _PARB_ #define ...
- c语言中定义宏的利与弊
在编写c文件时,我们都喜欢用宏来定义一些常量或者函数,这样增加了程序的可读性!但是我们有没有想过使用宏定义时可能出现问题呢?下面就简单举几例来说明宏定义的弊端! 例1: #define jia(m,n ...
- systemverilog 宏定义 `define 用法。
#将宏定义转化成字符串 `define stringfy(x) `"x`" string s; s = `stringfy(`macro);#此时宏`macor不可以有输入,否则报 ...
- java中宏定义,宏定义的使用
C中的宏分为两类,对象宏(object-like macro)和函数宏(function-like macro). 预定义宏: 1.预定义宏的行为是由编译器指定的. 2.前后双下杠的一般都是预定义. ...
- C语言中宏定义宏编译的使用#if,#ifdef,#ifndef,#elif,#else,#endif,defined使用详解,可以实现和if else一样的效果
#define 定义一个预处理宏 #undef 取消宏的定义 #if 编译预处理中的条件命令,相当于C语法中的if语句 ...
- java define 宏_宏定义宏函数(日志输出)define
最常见的就是 #indef __cplusplus 这表示支持C++语法 再如可以定义常量 #define MAX 100 这跟JAVA全局变量有什么区别呢? JAVA的变量是有类型的,这没有类型,这 ...
- C语言——数组定义及用法
目录: 一:定义 二:声明数组 三:初始化数组 数组赋值的区别 四:二维数组 五:多维数组 六:传递数组给函数 1.方式 一 2.方式 二 3.方式 三 七:从函数返回数组 八:指向数组的指针 来自: ...
- 宏定义宏函数 if else语句报错:error: ‘else’ without a previous ‘if’(看似解决实际上没解决)
代码 #include <stdio.h> #include <stdlib.h>#define ALOGE(...) { printf(__VA_ARGS__); print ...
- C语言-宏定义#define的用法
目录 1 不带参宏定义 2 带参宏定义 3 与字符串有关的用法 3.1 字符串转换 3.2 字符转换 3.3 字符连接 1 不带参宏定义 这种用法是最简单最常见的一种方式,如下: #define PA ...
最新文章
- CodeForces - 600E Lomsat gelral(树上启发式合并)
- getchar()和EOF
- 数据结构与算法入门---数据结构类型
- 关于java的集合类,以及HashMap中Set的用法!
- hdu_5761_Rower Bo(xjb猜公式)
- Druid的Segment Balance及其代价计算函数分析
- 罕有数据库系统之比拟 - Oracle数据库
- 打开终端报错:bash: /某路径/bashrc: No such file or directory
- Android模拟器 使用 Fiddler抓包
- 微信公众号迁移及公证书快速办理流程
- java 图片 加边框_给图片加图片边框 图片边框要求为PNG格式
- 正则表达式Regix
- Android中获取手机内所有应用信息
- Teamcenter RAC 调用查询
- Odoo开发需要注意些什么?
- 全球与中国聚合支付平台市场深度研究分析报告
- 分割速度最快的视频分割器
- vue图片img加载失败显示自定义默认图片(缺省图)
- 以三字游戏为例的模拟项目工程的实现与布局
- linux更换包管理工具,linux 软件包管理