`({...})`如何返回一个值?

时间:2011-10-19 20:19:39

标签: c gcc

我最近发现了这个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)这样做的首选方式是什么?

2 个答案:

答案 0 :(得分: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两次。

答案 1 :(得分:9)

({ ... })构造是gcc扩展名。

typeof运算符也是如此。

MAX宏(注意所有大写字母的常规用法)很容易写:

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

它会多次评估其中一个参数,因此您不应将其作为MAX(x++, y--)调用。全部大写字母的使用用于提醒用户它是一个宏,而不是一个函数,并且要注意带有副作用的参数。

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