C语言 - 预处理详解(一)#预定义符号 ##define #undef

C语言基础知识:#undef及其用法 在一个程序块中用完宏定义后,为防止后面标识符冲突需要取消其宏定义。/******** 例程1:main.c ********/在一个程序段中使用完宏定义后立即将其取消,防止在后面程序段中用到同样的名字而产生冲突。将某个库函数包装成自定义接口,而只允许用户调用自定义接口,禁止直接调用库函数。(此例来源于《C和指针》)/*** 定义一个不易发生错误的内存分配器*/#define malloc //防止直接调用malloc。 阅读详情


前言

路漫漫其修远兮,吾将上下而求索;


一、预定义符号

在C语言本身便预定义了一些符号,这些符号是可以直接使用的;

__FILE__       //进行编译的源文件(文件名:路径+主干名+后缀) %s

__LINE__       //文件当前的行号  %d

__DATE__      //文件被编译的日期  %s

__TIME__       //文件被编译的时间  %s

__STDC__      //如果编译器遵循 ANSI C,其值为1,否则未定义 %d

注:这些预定义符号在预处理阶段C语言本就定义好了的(这些预定义符号均是语言内置),是可以直接使用;当然,预定义符号出了上述列出来的几个,还有其他的,只不过这几个最常使用;

这些预定义符号有什么用呢?

例如,下面的代码便是在屏幕上打印出了目标数字:

但是,“打印”究竟是在文件的那个地方、其代码在哪一行、什么时候进行打印的呢?我们是否能记录一下呢?此时便可以用到 __FILE__、__LINE__、__DATE__、__TIME__使用如下:

__STDC__: 如果编译器遵循ANCI C,其返回值为1,否则未定义;故,倘若你想要知道VS编译器是否遵循ANSI C标准便可以用__STDC__ 来测试一下;此预定义符号的具体使用如下:

注:Linux 环境下的 gcc 编译器是遵循ANSI C标准的,这也就是为什么有些语法在测试的时候,在VS下的结果会与在gcc 编译器下的结果不同,当出现这一情况的时候,要以 gcc 编译器的结果为准,因为gcc 编译器才是严格符合ANSI C标准的编译器;

看了上述的注解,你可能会问:DevC++呢?

  • DevC++ 对于标准的支持不严谨,故而你会发现倘若在DevC++ 中写的代码是非常随意的,体现在:你写的语法很糟糕但是该编译器识别不出错误;所以在OJ网站上,一般就是要么使用gcc ,要么使用 clang (苹果公司所维护的编译器);

想必你会有疑问,这些预定义符号有什么用呢有什么用呢?

  • 显然,当我们想知道当前代码在哪个文件哪一行什么时间运行的时候,便可以利用这些预定于符号,故而也不会对获取其行号而发愁;

未来在哪里可以用到这些预定于符号?

  • 记录日志(即将这些信息写入文件之中)

二、#define 

(一)、#define 定义的标识符

语法: #define name stuff

使用如下:

#define MAX 1000     //定义了一个标识符常量MAX

#define reg register     //为register 这个关键字创建一个简短的名字 reg

#define do_forever for(;;)     //用更加形象的符号来替代一种实现(甚至可以是一段代码)

#define CASE break;case    //在写case 语句的时候自动把break 写上

#define DEBUG_PRINT printf("file: %s line=%d  \

                                               date:%s time:%s \n", \                                                                                                                  __FILE__,__LINE__,  \

                                                 __DATE__,__TIME__)

注:如果定义的stuff 过长,可以分成几段,除了最后一行外可以在每一行的后面都添一个反斜杠(续行符),并且在此续行符后面不可以再添加其他的东西;

续行符的作用?

  • 相当于转义了回车,让回车不再是回车;如果在续行符后面添加了一个空格,那么此续行符转义的便不再是回车,而是其后的空格 --> 没有转义回车而将一条语句分成了多段--> 报错;

#define 定义的标识符究竟是如何操作的?

  • #define 定义的标识符是在预处理阶段被替换掉,同时会删除该符号;

注:在 test.i 文件中不难发现在我们编写的代码前面有很多行代码,显然这是<stdio.h> 中的文件,故而不要频繁多次地包含头文件;

在#define 定义的标识符后面可不可以添加 ;  ?

例如这样:

#define DEBUG_PRINT printf("file: %s line=%d  \

                                               date:%s time:%s \n", \                                                                                                                  __FILE__,__LINE__,  \

                                                 __DATE__,__TIME__);

#define MAX 100;

这样写是不推荐的,因为容易写出 bug ;

为什么?

纵使 #define 定义的是一条语句,也不要加 ;  , 因为当你在调用此条语句的时候还会在其后面加 ; (利于代码的可读性)

(二)、#define 定义的宏

#define 机制包括了一个规定,允许把参数替换到文本之中,这种实现通常称为宏(macro)或者定义宏(define macro)

宏的申明方式: #define name(parament-list)  stuff

注:

  • 其中的parament-list 是一个由逗号隔开的符号表,它们可能出现在 stuff 中;
  • 参数左括号必须与name 紧挨;倘若参数左括号与name 之间有任何的空白存在,均会将该参数列表被解释为stuff 的一部分;

使用如下:

#define  SQUARE(X)  X*X

#define 定义的宏与#define 定义的标识符有什么区别:

  • #define 定义的宏是有参数的,而#define 定义的标识符没有参数;

宏的使用如下:

#define 定义的宏仍然是替换;

正式由于宏的本质是替换,那么就极容易出现操作符优先级先后的问题,上述代码存在的问题如下图所示:

特别注意,宏的参数不是计算传入宏体的,而是替换进行的;故而,倘若没有使用 () 来保证宏体中的操作符的优先级,而宏参数不一定只是单单的一个数字,如若也是表达式,那么极易出现操作符优先级带来实际的计算顺序与预期的计算顺序不相符的情况;

所以此处就得将宏中的参数当作一个整体,修改如下:

同理,既然宏参数与宏体之间存在操作符的优先级关系,那么宏也不单单是单独使用,即宏体与其外面的数字可能也会存在操作优先级的问题,例如:

所以也要将宏体当作一个整体;

核心在于,宏的本质是替换,要考虑到宏参数、宏体以及宏参与计算时与其周围操作符的优先级关系,所以就要利用括号将宏参数与宏体括起来,以保证其计算的顺序;

(三)、#define 替换规则

在程序中扩展 #define 定义的符号和宏时,需要涉及以下三个步骤:

  • 在调用宏时,首先要对其参数进行检查,看看是否包含任何由 #define 定义的符号,如果是,它们首先被替换(首先替换#define 定义的符号)
  • 所要替换的宏体会被插入到程序中原本使用宏的位置,而对于宏、参数名被宏体所替换;(然后替换#define 定义的宏)
  • 再次对结果文件进行扫描,看看它是否包含了任何对 #define 定义的符号,如果是便就重复上述操作;(最后再次检查)

上述步骤图解如下:

注:

1、宏参数和 #define 定义中可以出现其他 #define 定义的符号。但是对于宏,不能出现递归;

2、当预处理器搜索 #define 定义的符号的时候,字符串常量的中内容并不会被搜索;

为什么宏不可以递归?

  • 因为宏是完成替换的,它与函数不一样;并不是因为在宏中不能写递归的原因是在于其没有限制条件,而是因为在语法上硬性不支持宏写递归;

(四)、# 和 ##

1、 # 的作用

在讲述 # 的作用之前,我们先来了解一下字符串的特性;

在C语言中,如若你想打印 "hello world" 可以这样写:,当然你还可以这样写: --> 实际上是在函数printf 中放了两个字符串,但最终会合并为一个字符串,字符串具有自动连接的特点;

基于此原理,我们便产生了一个想法:

经过思考,你会发现,此处只能封装成宏,而非函数;

为什么不能封装成函数呢?

  • 因为如若你要封装成一个函数,那么此函数的内部功能要统一才行,而上图中是针对不同的变量而输出不同的对象名称,所以此处不能用函数;

既然如此,变量名如何传入?换句话说,如何将参数插入字符串中?

可能你首先会想到这么写:,但实际上认真思考会发现,N放在字符串中,而宏无法在字符串中被预处理器搜索,故而字符串中的N并不会替换,例子如下:

此时的字符串中的N成了一个普普通通的字符;

联系到,前面将两条字符串放在printf 函数中但最后合并成了一个字符串,你可能会说将"the value of" 与"is %d\n" 分为两条字符串,然后中间放宏参数,具体实现如下:

毫无疑问,这也是不行的,因为只有字符串相邻放在一起才能合成为一条字符串,N 单独放在两字符串中间肯定会出错况且函数printf 也不允许这么操作;

此时便会用到 #

#  --> 将一个宏的参数变成对应的字符串

那么此时 #N 便已然是个字符串,便就可以和字符串相邻放在一起而合并成一条字符串;

使用如下:

还可以利用宏来处理打印不同类型数据的问题;因为不同类型的数据对应着不同的占位符,所以此时的宏会有两个参数:变量以及此数据所对应的占位符;使用如下:

2、## 的作用

## 可以把位于它两边的符号合并成一个符号,并且允许宏定义从分离的文本片段创建标识符

#define ADD_TO_SUM(num , value)  sum##num+=value

ADD_TO_SUM (10,20);  -->  sum10+=20; 即让 sum10 增加20;

注:这样的连接必须产生的是一个合法的标识符。否则其结果就是未定义的;

注:在预处理之中的 ## 可以将两个符号合并成一个符号;并且允许宏定义从分离的文本片段创建标识符;

## 的使用(在实际的写代码中,## 用得非常少):

当我们利用#define 定义了一个函数,

注:上述代码相当于,利用宏写出了一个“函数模具”,函数的参数具有特定类型,与宏相结合便可以保留函数的大体框架,而利于替换函数的参数类型、返回类型,并利用## 实现函数名的“定制”;

(五)、带副作用的宏参数

当宏参数在宏的定义(宏体)中出现超过一次的时候,如若参数带有副作用,那么你在使用这个宏的时候就可能出现危险,而导致不可预测的后果。副作用就是表达式求值的时候出现有永久性效果;

什么叫做副作用?

  • 在现实生活中,以生病为例子,倘若一个人生病了,医生给他开的药治疗他的病的同时可能会给他带来副作用(副作用即是产生不良的反应);在代码之中,便体现为,我"帮助"了别人,结果改变了自己,例如 int a  = 2 ; int b = ++a ;  --> 此处的b 确实能得到值3,但是在这过程中 a 的值变了;于是乎此式便带有副作用;存在两个作用:为b 赋值、 更改a 的值;其中更改a 的值便为副作用;

对于宏而言,如下图:

显然,当宏参数有副作用的时候,所得到的结果脱离了我们设计该宏的目的;

上述的问题是什么出来的呢?

我们先来回顾一下三目操作符(条件操作符),计算规则:从左到右依次计算, 其具体实现细节如下图所示:

分析上述代码计算的过程:

从上述代码中,你可以发现,像 a++ , b++ 这种带有副作用的宏参数,并不是单单地只执行一次,当 (a++ > b++ )为真的时候,便会让 a++ 执行两次,而当 (a++ > b++ )为假的时候,便会让 b++ 执行两次;这样的代码时十分危险的,因为其结果难以预测;

(六)、宏和函数的对比

宏能完成的任务同样函数也可以,二者究竟有何区别?

例,就上图中求取最大值而言,宏与函数哪个更好?

于此例中,从参数类型的角度来看,宏没有参数类型的检查,可适用于很多的类型,故而显得非常灵活;而函数对参数类型的要求很严格;

从执行速度来看,相较于函数,宏的速度更快。为什么呢?

因为宏的本质是替换,还是以上述例子为例;

上述代码利用宏而比函数好的原因:

  • 1、用于调用函数(传参、函数栈帧的开辟)和从函数返回(函数可能会返回数据)的代码可能比实际执行这个小型计算工作所需要的时间长,所以宏比函数在程序的规模和速度方面更胜一筹;
  • 2、函数的参数必须声明为特定的类型,而宏的参数与类型无关;函数只能在类型合适的表达式上使用,而宏适用于可用于计算该式的所有类型;

但是宏也不是万能的,他也存在缺点:

  • 每次使用宏的时候,一份宏定义的代码插入到,倘若其代码很长,而又多次使用到该宏,那么便会大幅度地增加代码的长度;
  • 宏是不可以进行调试的;
  • 宏的参数与类型无关,显得不严谨;
  • 宏可能会带来运算符优先级的问题,而导致程序容易出错;
  • 宏不可以递归

注:宏的处理是在预处理阶段进行的,而调试调试的是编译、链接产生的可执行程序;

看了上文,你可能会有疑问,宏能实现的,函数也能实现,那么有没有宏能实而函数不能实现的情况呢?

  • 总所周知,函数的参数不能单单是类型,但是介于宏的本质实现是替换,所以宏参数可以是类型;

在前面学习动态开辟的时候,是否有这样的感觉,例如利用malloc 开辟空间,那么就得计算所要开辟的空间的字节数,针对不同类型的数据、存放此数据的个数来计算开辟的空间的大小,其计算过程便容易出现问题,为了减少bug 的出现,那么此时便可以利用宏来实现,代码如下:

#include<stdio.h>

#define MALLOC(num,type) (type *)malloc((num)*sizeof(type))

int main()
{
	short* p1 = MALLOC(10,short);
	if (p1 == NULL)
	{
		perror("malloc short");
		return;
	}
	int* p2 = MALLOC(20, int);
	if (p2 == NULL)
	{
		perror("malloc int");
		return;
	}
	
	return 0;
}

宏与函数的对比:

属性#define 定义宏函数
代码长度每次使用宏的时候,宏代码都会被插入到程序中;倘若宏的代码行很多,多次使用该宏便会使得该程序的代码行大幅度增长函数具体实现的代码只会出现在一个地方;每次使用这个函数的时候,都会那个地方的函数;不会因多次调用函数而大幅度地增加代码行
执行速度宏的本质是替换,且在预处理阶段完成的,只有执行该代码的时间开销,故而其执行速度会更快存在函数的调用和返回结果的时间上的开销,故而相对来说会慢一些
操作符的优先级宏的本质是替换;宏参数求值是在所有周围表达式的上下文环境里,故而其邻近操作符的优先级可能会影响宏体中的实现,进而导致实际结果会与预期结果不相符的情况;所以在写宏的时候,要为宏参数与宏体加上括号,以保证其计算的顺序;函数参数只在函数调用的时候求值一次,它的结果值传递给函数;表达式求值的结果更容易预测;
带有副作用的参数宏参数可能会被替换到宏体中的多个位置,倘若此宏参数带有副作用,那么便会进行多次计算,从而导致所得到的结果会偏离使用的目的,即产生不可预测的结果;函数传参只在传参的时候求值一次,即无论是传址还是传值,本质均是函数针对所传递过来的数据进行操作,所以结果更容易控制;
参数类型宏的参数与类型无关,只要对参数的操作合法,那么此宏便可以适用于任何类型的参数。函数的参数是与类型有关的,如果参数的类型不同,就需要不同的参数,即使他们执行的任务是相同的;
调试宏不能调试函数可以逐语句进行调试
递归宏不能递归函数可以递归

怎么判断在一个条件下该使用宏还是使用函数呢?

  • 如果说该代码足够简单,那我们便可利用宏来写;倘若该代码写出来很复杂、行数多并且容易出错,介于宏不能进行调试,便无法观察执行的细节,所以我们便可以使用函数来解决问题;(注:当然,使用c++ 可以不用纠结于到底使用宏还是函数了; 因为在 c++ 之中提供了概关键字 inline(内联函数),inline 具有了函数的优点和宏的优点;)

(七)、命名约定

如此看来函数与宏在使用的语法上很相似,既然无法利用语言来帮我们区分二者,那么有什么办法能帮助我们区分二者呢?

  • 将宏名全部大写
  • 函数名不全部大写

注:但是也不要以为全是小写的一定是函数,例如: offsetof 全是小写,咋一看以为是函数,其实offsetof 本质上是宏; 函数getchar 中有部分实现可能利用了宏;

此处只是个约定,总有人不按照套路来走,所以“全大写是宏” 这种判断是宏还是函数的方法只是一种参考,具体靠谱地判断还是得结合代码;

三、#undef

#define 可以用来定义标识符,也可以用来定义宏,那么其定义能否被取消呢?

  • 利用#undef 便可以实现

#undef   用于移除一个宏定义;


总结

1、在C语言本身便预定义了一些符号,这些符号是可以直接使用的;

__FILE__       //进行编译的源文件(文件名:路径+主干名+后缀) %s

__LINE__       //文件当前的行号  %d

__DATE__      //文件被编译的日期  %s

__TIME__       //文件被编译的时间  %s

__STDC__      //如果编译器遵循 ANSI C,其值为1,否则未定义 %d

2、#define 定义的标识符

语法: #define name stuff

3、#define 机制包括了一个规定,允许把参数替换到文本之中,这种实现通常称为宏(macro)或者定义宏(define macro)

宏的申明方式: #define name(parament-list)  stuff

注:

  • 其中的parament-list 是一个由逗号隔开的符号表,它们可能出现在 stuff 中;
  • 参数左括号必须与name 紧挨;倘若参数左括号与name 之间有任何的空白存在,均会将该参数列表被解释为stuff 的一部分;

4、#  --> 将一个宏的参数变成对应的字符串

5、## 可以把位于它两边的符号合并成一个符号,并且允许宏定义从分离的文本片段创建标识符

6、#undef   用于移除一个宏定义;

C++预处理命令 #undef的用法详解 在上述代码中,首先我们使用#define来定义了一个常量PI,并在main函数中输出了它的值。然后在程序的中间部分,我们使用#undef来取消了PI的定义。总结一下,#undef命令主要用于取消宏定义,将其从定义表中删除。不过,由于取消定义会影响到未来的代码,因此需要谨慎使用。使用该命令会影响到未来的代码,因此需要谨慎使用。#undef就是C++预处理命令中的一个。可以看到,在输出PI的值之后,程序成功地取消了PI的定义,并输出了“PI undefined.”这个提示信息。 阅读详情

相关推荐

C++ 预处理命令 #undef 的用法

然后,我们在主函数中输出了宏的值。预处理命令 #undef 是预处理阶段的一种指令,用于取消已定义的宏。总结一下,C++ 预处理命令 #undef 的作用是取消已定义的宏。通过使用 #undef,我们可以在代码中灵活地控制宏的作用范围,并根据需要定义和取消定义宏。然而,有时候我们可能需要取消一个已经定义的宏,这时就可以使用 #undef 命令。需要注意的是,取消定义一个未定义的宏是无效的,并不会引发编译错误。通过使用 #undef 命令,我们可以在代码的不同部分取消定义宏,这样可以灵活地控制宏的作用范围。

PixelDude的博客 455

#define详解

#define定义标识符,#define定义宏,#define 替换规则, #和##, 带副作用的宏参数,宏和函数对比

m0_62518756的博客 1万+

思澈sdk-新建lcd

co5300至此有3个同ID的驱动,在co5300xxxx.c的LCD_DRIVER_EXPORT(co5300, LCD_ID, &lcdc_int_cfg, &CO5300_drv, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT, 2);2 在customer\peripherals\Kconfig_lcd中添加如下配置(注意修改的地方有两个LCD_USING_TFT_CO5300_143)5 在该文件中的config LCD_DPI配置项下添加:(这里300为DPI)

gongyuan073的专栏 1385

【C语言】预处理详解:#define的各种使用方法

define定义标识符的用法非常简单语法:name可以由自己来命名,尽量取一些有意义的名字stuff是名字所对应的内容#define还可以用来定义关键字#define reg register //为 register这个关键字,创建一个简短的名字我们如果觉得register太长了,使用不方便,我们还可以创一个简单的名字reg上面这个reg的意思就是register可以看到 reg被替换成了register。

wangduduniubi的博客 3万+

VC Spyglass CDC验证避坑指南:如何正确配置同步复位信号(实验二重点解析)

本文深入解析VC Spyglass CDC验证中同步复位信号的正确配置方法,通过实验二案例详细展示错误配置的典型表现及修正过程。文章提供同步复位的最佳实践方案,包括约束文件修改指南、验证流程优化建议和高级调试技巧,帮助工程师有效避免CDC验证中的常见陷阱。

rock5的博客 678

当AI学会自我验证:Chain-of-Verification如何杜绝错误决策?

2025年,大模型"幻觉"问题已成为企业落地AI的最大障碍之一——金融风控中1.2%的误判率可能导致千万级损失,医疗诊断中3%的错误可能危及生命,法律文书中5%的事实偏差可能引发合规风险。MetaAI与Google联合提出的**Chain-of-Verification(CoVe,验证链)**技术,让AI具备"自我审视"能力,通过结构化验证流程将幻觉率降低68%+,在复杂决策场景准确率提升至95%+。本文系统拆解CoVe的技术原理、实施路径与行业实战,为企业提供AI决策可靠性保障的完整方案。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1081

#define 宏定义看这一篇文章就够了

本文旨在重浅入深,全方面解析 #define 的基础用法,使用的隐患,带来的副作用,与函数的相似和不同,详细的对比了宏定义和函数的细节以及功能和性能

luming的博客 4万+

5个实战必备的多模态情感分析数据集(附下载链接与避坑指南)

本文精选了5个实战必备的多模态情感分析数据集,包括CMU-MOSEI、CH-SIMS、UR-FUNNY、MUStARD和IEMOCAP,并提供了详细的下载链接与避坑指南。文章重点介绍了如何高效获取、预处理这些数据集,并自然整合了多模态情感分析的核心热词,旨在帮助研究者和开发者快速启动项目,规避常见陷阱,聚焦模型创新。

yolo5detector的博客 280

#define 详解

#define 详解 #与## #undef

weixin_74837727的博客 4590

【星火】海思HI3516C开发板实战:基于LVGL与MPP库的行车记录仪/电子显微镜方案

本文详细介绍了基于海思HI3516CV500开发板,结合LVGL图形库与海思MPP媒体处理平台,实现行车记录仪与电子显微镜方案的完整实战过程。内容涵盖从系统环境搭建、驱动配置到应用开发的全流程,重点解析了MPP视频流处理管道与LVGUI界面协同工作的核心机制,为嵌入式音视频开发提供了可复用的参考方案。

weixin_42126677的博客 160

GBase8a-GDCA认证考试-复习参考题

为提升产品服务水平定期举办GBase产品认证培训,培训更多GBase数据库专业人员,满足用户快速成长的业务需求,建设GBase产品生态。请注意甄别,根据所学知识综合判断,正确率97%(97分)。

weixin_41826637的博客 2374

C语言之#define用法入门详解

在C语言中,常量是使用频率很高的一个量。常量是指在程序运行过程中,其值不能被改变的量。常量常使用#define来定义。 使用#define定义的常量也称为符号常量,可以提高程序的运行效率。

sunnyoldboy博客 4万+

ADC实现模数转换Multisim电路仿真——硬件工程师笔记

8位模数转换器(ADC)是将模拟信号转换为8位数字信号的电子器件,具有256级量化能力。其工作原理分为采样、量化和编码三个阶段,关键参数包括分辨率、采样率、精度、线性度和信噪比。常见型号有ADC0804、ADC0808等,广泛应用于数据采集、音频处理、通信系统和消费电子产品中。典型应用时需要配置参考电压、模拟输入和数字输出引脚,并通过仿真实验验证转换效果(如-10V对应输出0,10V对应255)。硬件工程师需掌握其原理和参数选择,相关笔试面试资料可在优快云博客获取。

XU157303764的博客 1508

[c语言]#define 详解

10;最常见的用法就是#define来定义一些常量.10int main()i < sz;i++)在define定义表示符时,建议不需在最后加上;如图:在预先编译后,编译器会将程序中带要标识符的位置与标识符所表示的信息产生文本替换,若#define所表示的表达式带有;号,则可能出现危险的错误!!!#define不仅仅可以表示常量,也可以表示一些表达式.它可以将参数替换到表达式中,再将表达式替换到程序中,这种行为通常称为宏.a : ba : ba : ba : b?a : ba : b。

Pear549669的博客 8858

智能家居系统设计:基于MATLAB的智能家居系统设计和仿真,包括智能家居控制、家庭能源管理和家庭安全监控

基于 MATLAB 的智能家居系统设计方法可以有效地解决各类智能家居问题。

走向CTO的路上... 1775

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

#define用法

C语言中,可以用 #define 定义一个标识符来表示一个常量。其特点是:定义的标识符不占内存,只是一个临时的符号,预编译后这个符号就不存在了。 预编译又叫预处理。预编译不是编译,而是编译前的处理。这个操作是在正式编译之前由系统自动完成的。 用 #define 定义标识符的一般形式为: #define 标识符 常量 //注意, 最后没有分号 #define 和 #include 一样,也是以“#”开头的。凡是以“#”开头的均为预处理指令,#define也不例外。#define又称宏定义,标识...

顺其自然~专栏 3万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

C语言中#undef的用法

C语言中#undef的语法定义是:#undef 标识符,用来将前面定义的宏标识符取消定义。 然而,在实际应用中,#undef到底可以用来做什么? 整理了如下几种#undef的常见用法。 1. 防止宏定义冲突 在一个程序块中用完宏定义后,为防止后面标识符冲突需要取消其宏定义。 例如: #include <stdio.h> int main() { #define MAX ...

丨晋丨 1万+

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

关于#define的使用方法总结

#define 是 C 和 C++ 编程语言中的预处理指令,用于定义宏(macro)。宏是一种预处理器功能,它允许程序员定义一个标识符(通常是大写字母),该标识符可以被替换为一段代码、表达式或常量值。,#define定义有参函数宏时要注意参数的运算优先级,一定要加括号保护参数

dearzhangxp的博客 5915

#define 的使用

使用#define来定义标识符和宏

challenglistic的博客 4940

【C语言】详解#define

#define 详解

yf214wxy的博客 1290

C语言——#define的使用

提高代码可读性: 常量可以帮助开发者理解代码的含义。例如,使用常量MAX_USERS比 使用数字100更能表达一个变量应该表示的最大用户数。便于维护: 如果一个值在程序中多次使用,比如一个应用的版本号,将其定义为常量(如VERSION)可以使得未来的更新更加容易。你只需要改变常量的定义,而不是每一个出现该值的地方。避免魔法数: 魔法数(Magic Numbers)是指在代码中直接出现的、没有解释的数字。使用常量代替魔法数可以增加代码的可读性和可维护性。配置管理。

Jason_from_China的博客 4418

(转载)#define、#undef、#ifdef、#ifndef、#if、#elif、#else、#endif、defined 的用法

转载来自:https://www.cnblogs.com/fazero/p/5016514.html) (转载来自:https://blog.youkuaiyun.com/qq_33658067/article/details/79443014) #ifndef 作用:防止头文件的重复包含和编译 定义   #ifndef x   #define x   ...   #endif   这是宏定义...

tyler880的专栏 2520

#define的用法和注意事项精讲

#define可以用来替换明示常量,还可以用来定义函数,各有需要注意的地方。

qq_45943899的博客 2549

#define的使用

目录 前言 1.#define定义标识符 2. #define定义宏 3.#define 替换规则 4.宏和函数对比 前言 在很多C程序中,我们会在一个源文件的开头看到#define的字眼,和define的英文解释相同——可以理解为给xxx下定义,这里可以是标识符甚至是一个函数,接下来的内容将会对#define进行详解 1.#define定义标识符 使用#define可以用来定义标识符,所谓标识符可以简单理解为一个能够表示一定内容的符号,其格式为 #定义 标识符...

weixin_58165485的博客 5万+

#define宏(重要)

define 常量名 值或表达式1、定义常量defineMAX 1000define2、简化名称define//为register这个关键字,创建⼀个简短的名字3、效果替换define;//⽤更形象的符号来替换⼀种实现for(;;)中判断条件为空则语句陷入死循环4、简略代码defineCASE break;case//在写case语句的时候⾃动把break写上5、如果定义的stuff过⻓,可以分⾏写,除了最后⼀⾏外,每⾏的后⾯加⼀个反斜杠(续⾏符)

m0_73975164的博客 747
上一篇: C语言-程序环境 #预处理 #编译 #汇编 #链接 #执行环境
下一篇: C语言 预处理详解(二) #命令行定义 #条件编译 #文件包含 #其他预处理指令
秦少游在淮海
博客等级 码龄3年 1071粉丝 88原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值