`({...})` 如何返回值?(该问题涉及IT技术)

11

最近我发现了这个GCC宏:

#define max(a,b) \
   ({ typeof (a) _a = (a); \
       typeof (b) _b = (b); \
     _a > _b ? _a : _b; })

在看到这段代码之前,我没有意识到 C 中一段 {...} 代码块可以返回值。

1) 你能给我一个提示,这是如何实现的吗?

尽管如此,我通常通过滥用逗号操作符来达到相同的结果:

#define max(a,b) \
    (typeof (a) _a = (a), \
     typeof (b) _b = (b), \
     (_a > _b ? _a : _b)) 

如果只是为了副作用,我会使用do { ... } while(0)

2) 哪种方法更受欢迎?


1
这可能会成为一个受保护的问题!许多C(和C ++,我相信)程序员不知道({...})是GCC扩展而不是C语言的一部分。在我看来。 - Jack
2个回答

10

这是GCC的一个扩展功能。逗号运算符无法使用:

// C89, doesn't work...
#define max(a,b) \
    (typeof (a) _a = (a), \
     typeof (b) _b = (b), \
     (_a > _b ? _a : _b)) 

逗号运算符仅适用于表达式,typeof(a) _a = (a); 是一个声明,而不是表达式。没有使用GCC扩展或C11(具有_Generic)几乎不可能编写等效的宏。请注意,typeof也是GCC扩展,因此除非您还消除typeof,否则通过消除({...})无法获得任何可移植性。
这是C11版本,与之相比非常冗长(仅处理两种类型!)。 C11甚至还没有得到支持,祝你好运尝试找到编译器来测试它:
// C11
static inline int maxi(int x, int y) { return x > y ? x : y; }
static inline long maxl(long x, long y) { return x > y ? x : y; }
#define max(x, y) _Generic((x), \
    long: maxl(x,y), \
    int:_Generic((y), \
        int: maxi(x,y), \
        long: maxl(x,y)))

在可移植的C99中,你可以编写一个宏或内联函数来实现相同的效果,但是每个宏只能适用于一种类型。
// C99
static inline int maxi(int x, int y) { return x > y ? x : y; }

在C89/C90中,我想不到任何方法来编写宏,使其不会评估xy两次。

7
请不要写一个毫无意义的答案。耐心等待,写出一份好的回答。如果它足够好,就会获得足够多的赞。不需要试图将问题归为自己名下。 - David Heffernan
抱歉,我正在使用一个不熟悉的终端,并尝试保存我的草稿,以免失去我所写的内容。我并不是真的想“将问题归为自己所有”。 - Dietrich Epp

9
"

({ ... }) 结构是 gcc 的一个扩展。

typeof 运算符也是如此。

MAX 宏(请注意传统的全大写用法)很容易编写:

"
#define MAX(a, b) ((a) > (b) ? (a) : (b))

它确实会对其一个参数进行多次评估,因此您不应该像这样调用它:MAX(x ++,y--)。全大写的使用提醒用户它是一个宏而不是函数,并且要小心具有副作用的参数。

或者您可以为每种类型编写一个函数(可能是内联函数)。


2
+1 哇 :-|,真的不知道 ({ ... })。他们应该完全把它放在语言中。 - cnicutar
2
感谢提供({...})链接!仅凭标点符号进行搜索总是很困难。 - Vladimir Keleshev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接