宏可以通过转换为void来模仿void返回函数吗?

时间:2015-05-26 14:27:56

标签: c macros void c89

所以...我有宏,它具有“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;

  }

1 个答案:

答案 0 :(得分:1)

  

以下函数/宏的行为是否相似(包括   当用作右值时,合法并激发编译时错误?

它们在正确使用时表现相似(即不在作业中),并且可能(但不一定)用作右值(见下文)。

只有正确使用它们才是合法的。

关于编译时错误,C89到C11的标准在环境/概念模型/翻译环境/诊断部分中的措辞与C89中的措辞非常相似(C99中添加了粗体文字):

  

符合要求的实施应至少产生一种诊断   每个人的消息(以实现定义的方式标识)   包含违反任何语法规则的翻译单元或   约束,即使行为也是明确的   指定为未定义或实现定义。不需要在其他情况下生成诊断消息   情况。

现在,当您使用函数/宏作为右值时,我们有两种情况。

  1. SET_MACRO_DW()
    它扩展到的do while语句在赋值表达式中明显违反了语法规则 assignment-expression ,因此必须生成诊断消息。

  2. setFunction()SET_MACRO_C2V()
    这些是 void表达式。作为右值,它们不违反任何语法规则,因此问题是是否存在违反任何约束的情况。 语言/转换/其他操作数/ void 部分中的以下措辞未从C89更改为C11。

      

    void expression 的(不存在的)值(具有的表达式)   类型void)不得以任何方式使用,也不得使用隐式或显式   转换(void除外)不适用于此类转换   表达

    此外,标准的措辞与

    非常相似
      

    在本标准中,“应”应被解释为对实施或计划的要求;相反,“不得”应被解释为禁止   ...
      如果违反约束之外出现的“必须”或“不应”要求,则行为未定义。

    现在,我无法确定 void expression 的上述要求是否构成约束,所以我问What are the Constraints in Standard C? 结论是上面不是标准意义上的约束,因此作为右值的使用不能保证错误消息(虽然应该由每个合理的编译器产生)和未定义的行为中使用结果。但是语言/表达式/赋值运算符/简单赋值部分仍存在约束:

      

    以下其中一项应持有:......

    其中没有以下内容,因此我们违反了约束,即使行为明确未定义,也会保证错误消息。

  3. 所以,SET_MACRO_DW()是你提出的三个中最简单,最简单的构造。

相关问题