所以...我有宏,它具有“SET”功能并且应该模仿一个会返回void的函数。我可以使用do {...} while(0)构造来实现此行为,但它是否合法,如果是这样,它实现定义的行为将某些内容转换为void以实现此操作? (根据不同版本的C标准,对我来说最重要的是:C89仍然存在)
更具体: 以下函数/宏的行为是否相似(包括在用作右值时合法并引发编译时错误)?
void setFunction(int * const pVar, const int intvalue) /* as function */
{
*pVar = intvalue;
return;
}
#define SET_MACRO_DW(pVar,intvalue) \
do { \
*(pVar) = (intvalue); \
} while (0)
#define SET_MACRO_C2V(pVar,intvalue) \
((void) (*(pVar) = (intvalue)))
void test()
{
int target;
int value = 17;
int retDummy;
setFunction(&target, value); /* ok */
SET_MACRO_DW(&target, value); /* ok */
SET_MACRO_C2V(&target, value); /* ok? */
retDummy = setFunction(&target, value); /* CT error/warning */
retDummy = SET_MACRO_DW(&target, value); /* CT syntax error */
retDummy = SET_MACRO_C2V(&target, value); /* ??? */
return;
}
答案 0 :(得分:1)
以下函数/宏的行为是否相似(包括 当用作右值时,合法并激发编译时错误?
它们在正确使用时表现相似(即不在作业中),并且可能(但不一定)用作右值(见下文)。
只有正确使用它们才是合法的。
关于编译时错误,C89到C11的标准在环境/概念模型/翻译环境/诊断部分中的措辞与C89中的措辞非常相似(C99中添加了粗体文字):
符合要求的实施应至少产生一种诊断 每个人的消息(以实现定义的方式标识) 包含违反任何语法规则的翻译单元或 约束,即使行为也是明确的 指定为未定义或实现定义。不需要在其他情况下生成诊断消息 情况。
现在,当您使用函数/宏作为右值时,我们有两种情况。
SET_MACRO_DW()
它扩展到的do
while
语句在赋值表达式中明显违反了语法规则 assignment-expression ,因此必须生成诊断消息。
setFunction()
和SET_MACRO_C2V()
这些是 void表达式。作为右值,它们不违反任何语法规则,因此问题是是否存在违反任何约束的情况。 语言/转换/其他操作数/ void
部分中的以下措辞未从C89更改为C11。
void expression 的(不存在的)值(具有的表达式) 类型
void
)不得以任何方式使用,也不得使用隐式或显式 转换(void
除外)不适用于此类转换 表达
此外,标准的措辞与
非常相似在本标准中,“应”应被解释为对实施或计划的要求;相反,“不得”应被解释为禁止 ...
如果违反约束之外出现的“必须”或“不应”要求,则行为未定义。
现在,我无法确定 void expression 的上述要求是否构成约束,所以我问What are the Constraints in Standard C?
结论是上面不是标准意义上的约束,因此作为右值的使用不能保证错误消息(虽然应该由每个合理的编译器产生)和在未定义的行为中使用结果。但是语言/表达式/赋值运算符/简单赋值部分仍存在约束:
以下其中一项应持有:......
其中没有以下内容,因此我们违反了约束,即使行为明确未定义,也会保证错误消息。
所以,SET_MACRO_DW()
是你提出的三个中最简单,最简单的构造。