【问题标题】:Function like macros returning a value类似宏的函数返回值
【发布时间】:2013-05-17 07:19:09
【问题描述】:

最近遇到以下示例,它返回寄存器读取 __ret 但没有返回语句

#define READWORD(offset)       ({ \
                 unsigned short __ret=0;\
                 __ret = readw(offset);\
                 __ret; \
                 })

谷歌上是否也发现了宏之类的函数可以返回值。假设最后一条语句“_ret”等同于返回一个值是否安全? 如果我在“_ret”之后有另一个改变 __ret 值的语句怎么办。哪个会被退回?

【问题讨论】:

标签: c macros


【解决方案1】:

这是使用名为 Statement Expressions 的 GCC 扩展。

除非您需要移植到 GCC(和 Clang/LLVM)以外的编译器,否则您可以使用它。

【讨论】:

  • 这是我从链接“复合语句中的最后一件事应该是一个后跟分号的表达式;这个子表达式的值作为整个构造的值。(如果您在大括号中最后使用某种其他类型的语句,该构造具有 void 类型,因此实际上没有值。)“据我了解,最后一条语句是宏的整个计算值。如果我错了,请纠正我
  • 那是正确的......在这个例子中,我不确定语句表达式与 #define READWORD(offset) ((unsigned short)readw(offset)) 相比有什么好处,#define READWORD(offset) ((unsigned short)readw(offset)) 是可移植的并且做同样的工作 AFAICS。一般来说,语句表达式中有些事情你可以做,但你不能没有。
【解决方案2】:

让我们分解一下。例如,让我们看看 READWORD(1) 会做什么。预处理器将插入: ( { 无符号短 __ret=0; __ret = readw(1); __ret; } )

现在我们可以看到它在做什么了。我们只是调用一个带有参数 (1) 的函数 readw 并将其分配给一个无符号的 short。之后我们只有 __ret; 行。尽管这是一个完全有效的陈述,但它似乎并没有做任何事情。但请继续阅读!

最后的 } 之后的一切都超出了范围。

但是,封闭的 () 使一切变得不同。整个事情优雅地是一个具有 __ret 值的表达式。因此,您可以为其分配一个变量。这使得整个事情在宏观参数中非常稳定。

这有助于解开吗?

【讨论】:

  • 您省略了展开文本周围的括号。它是对标准 C 的特定于 GCC 的扩展;除了 Clang/LLVM(部分基于 GCC)之外,它不可移植。
  • 糟糕。放进去!我永远不会在实践中使用它,因为它的习语太过分了,并且让源代码控制维护者感到困惑。我的意思是,我的解释很混乱,不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-09
  • 2012-01-29
  • 1970-01-01
相关资源
最近更新 更多