da{...}while(0)

2024-04-21 17:18
文章标签 da

本文主要是介绍da{...}while(0),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先,先看一下这个例子:

1
2
#define __set_task_state(tsk, state_value)      \
     do  { (tsk)->state = (state_value); }  while  (0)

在Linux内核和其它一些著名的C库中有许多使用do{...}while(0)的宏定义。这种宏的用途是什么?有什么好处?

Google的Robert Love(先前从事Linux内核开发)给我们解答如下:

do{...}while(0)在C中是唯一的构造程序,让你定义的宏总是以相同的方式工作,这样不管怎么使用宏(尤其在没有用大括号包围调用宏的语句),宏后面的分号也是相同的效果。

这句话听起来可能有些拗口,其实用一句话概括就是:使用do{...}while(0)构造后的宏定义不会受到大括号、分号等的影响,总是会按你期望的方式调用运行。

例如:

1
#define foo(x) bar(x); baz(x)

然后你可能这样调用:

1
foo(wolf);

这将被宏扩展为:

1
bar(wolf); baz(wolf);

这的确是我们期望的正确输出。下面看看如果我们这样调用:

1
2
if  (!feral)
     foo(wolf);

那么扩展后可能就不是你所期望的结果。上面语句将扩展为:

1
2
3
if  (!feral)
     bar(wolf);
baz(wolf);

显而易见,这是错误的,也是大家经常易犯的错误之一。

 

几乎在所有的情况下,期望写多语句宏来达到正确的结果是不可能的。你不能让宏像函数一样行为——在没有do/while(0)的情况下。

如果我们使用do{...}while(0)来重新定义宏,即:

1
#define foo(x) do { bar(x); baz(x); } while (0)

现在,该语句功能上等价于前者,do能确保大括号里的逻辑能被执行,而while(0)能确保该逻辑只被执行一次,即与没有循环时一样。

对于上面的if语句,将会被扩展为:

1
2
if  (!feral)
     do  { bar(wolf); baz(wolf); }  while  (0);

从语义上讲,它与下面的语句是等价的:

1
2
3
4
if  (!feral) {
     bar(wolf);
     baz(wolf);
}

这里你可能感到迷惑不解了,为什么不用大括号直接把宏包围起来呢?为什么非得使用do/while(0)逻辑呢?

例如,我们用大括号来定义宏如下:

1
#define foo(x)  { bar(x); baz(x); }

这对于上面举的if语句的确能被正确扩展,但是如果我们有下面的语句调用呢:

1
2
3
4
if  (!feral)
     foo(wolf);
else
     bin(wolf);

宏扩展后将变成:

1
2
3
4
5
6
if  (!feral) {
     bar(wolf);
     baz(wolf);
};
else
     bin(wolf);

大家可以看出,这就有语法错误了。

 

总结:Linux和其它代码库里的宏都用do/while(0)来包围执行逻辑,因为它能确保宏的行为总是相同的,而不管在调用代码中使用了多少分号和大括号。

 

这篇关于da{...}while(0)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/923624

相关文章

C#编写上位机通过OPC DA读取西门子PLC数据

Sync_RW 引用:Quick.OpcComRcw 文档中原程序会报错: 原因:需要在安装有Simatic NET V14的电脑上运行这个程序。 需要注释掉下面程序,否则读取时会无故障提示退出。 //finally里的程序要注释掉,否则一点击read按钮,程序会直接无故障提示退出//finally//{// // Free the unmanaged memory/

Walrus:去中心化存储和DA协议,可以基于Sui构建L2和大型存储

Walrus是为区块链应用和自主代理提供的创新去中心化存储网络。Walrus存储系统今天以开发者预览版的形式发布,面向Sui开发者征求反馈意见,并预计很快会向其他Web3社区广泛推广。 通过采用纠删编码创新技术,Walrus能够快速且稳健地将非结构化数据块编码成较小的分片,这些分片会分布存储在一个存储节点网络中。即使多达三分之二的分片丢失,也可以使用部分分片快速重构原始数据块。这在保持复制因子仅

运行hbase shell时报错: hbase(main):001:0 list ERROR: Can't get master address from ZooKeeper; znode da

运行hbase shell时报错: hbase(main):001:0> list ERROR: Can't get master address from ZooKeeper; znode data == null Here is some help for this command: List all tables in hbase. Optional regular expressio

第六讲:AD、DA的工作原理及实现、运放电路

DA   数模转换器 (DAC) 数模转换器(Digital-to-Analog Converter,简称DAC)是一种将数字信号转换为模拟信号的电子装置。DAC在各种电子设备中广泛应用,如音频设备、通信系统、测量设备和控制系统中。以下是DAC的主要概念和应用。

The game of Fort/Da是自虐还是自保?

“The game of Fort/Da”出自佛洛伊德的《The interpretation of dreams》(1990a, p339-625),这里的fort可译为英文里的gone, da译为there,原本用于描述幼儿的一种值得深究的行为模式。佛洛伊德发现自己18个月大的小孙子Ernst对一个游戏乐此不疲,他不断的抛出他能抓住的小物件并兴奋且满足地大声嚷着“fort",后来他开始迷上一个

【DA-CLIP】图像复原在AutoDL上部署测试

起因: 虽然在本机Windows部署成功运行,但是由于计算资源少只有6G的GPU无法计算手机拍摄图像复原和其他一些数据集测试,尝试租用AutoDL的服务器部署测试 租AutoDL  租的人很多,刚确定运行的镜像环境就报告说这个机子已经没卡了,又换了一台4090 上传权重文件、项目文件  没用网盘和filezilla那些AutoDL帮助文档,一开始AutoDL文件存储 传了不同区,

Maratona de Programa¸c˜ao da SBC – ICPC – 2019 G Getting Confidence(最大费用最大流)

题目链接:https://codeforces.com/gym/102346/problem/G   题目大意:给一个n*n矩阵,每一行每一列最多选出一个元素,求他们乘积最大值(n和数字范围都是1~100)   题目思路:应该对每一行每一列只能取一个这种题目很敏感了啊!就是个二分图啊!n个行n个列,源点向每一行连容量为1,费用为0的边,每一列向终点也这么连,然后每一行都向每一列连,需要注意

【DA-CLIP】图像退化类型检测功能演示代码

背景 在CLIP基础上微调而来,使用图像控制器编码生成退化类型embedding并在训练中对图像编码器进行控制。针对十种退化类型进行了训练。 解决CLIP模型在图像纹理等层面无法针对退化类型识别或识别率较低的问题。 训练数据集情况  GitHub有对应数据集连接   完整代码 项目没有提供退化类型识别准确率计算的代码。只提供了上面的雷达图对比。毕竟这只是复原处理的一小部分。

嵌入式基础知识学习:DA/AD—数模/模数转换

AD/DA—数模/模数转换概念 数字电路只能处理二进制数字信号,而声音、温度、速度和光线等都是模拟量,利用相应的传感器(如声音用话筒)可以将它们转换成模拟信号,然后由A/D转换器将它们转换成二进制数字信号,再让数字电路对它们进行各种处理,最后由D/A转换电路将数字信号还原成模拟信号。 ADC是模拟到数字转换器(Analog-to-Digital Converter)的缩写。它是一种电子设备或模

2024/4/15 AD/DA

AD(Analog to Digital):模拟-数字转换,将模拟信号转换为计算机可操作的数字信号 DA(Digital to Analog):数字-模拟转换,将计算机输出的数字信号转换为模拟信号 AD/DA转换打开了计算机与模拟信号的大门,极大的提高了计算机系统的应用范围,也为模拟信号数字化处理提供了可能 AD转换通常有多个输入通道,用多路选择开关连接至AD转换器,以实现AD多路复用的