检测C编译器是否支持语句表达式

4

有没有办法检测编译器(我有一个支持它们的当前 GCC 和一个不支持的老旧的 clang)是否实现了语句表达式,以便我可以像这样做:

#ifdef NO_COMPOUND_STATEMENTS
#define MIN(a,b)    ((a)<=(b) ? (a):(b))
#define MAX(a,b)    ((a)>=(b) ? (a):(b))
#else
#define MIN(a,b) ({ __typeof__ (a) _a=(a); __typeof__ (b) _b=(b); _a<_b ? _a : _b; })
#define MAX(a,b) ({ __typeof__ (a) _a=(a); __typeof__ (b) _b=(b); _a>_b ? _a : _b; })
#endif

3
“Compound statement”是该语言的一项基本功能,因此自编译器问世以来每个C编译器都有此功能。并不存在没有“compound statements”的C编译器。与此同时,您似乎在谈论statement expressions - AnT stands with Russia
1
你可以贴出一个你的Clang编译器不支持的例子吗? - Bathsheba
1
你所描述的“复合语句”功能似乎实际上是能够将复合语句作为表达式使用的能力。标准C的任何版本都不支持此功能;这是GCC的扩展。可能其他实现也支持它,但不能有任何标准的测试方法来专门测试它,因为它本身就不是标准。 - John Bollinger
3个回答

1
正如AnT在他们的答案中所述,它们不是标准的一部分。不幸的是,我也找不到GCC中的任何特性测试宏的证据,因此您最好检查以确保您正在使用C标准的gnu变体和GCC版本3或更高版本(这是添加语句表达式的时间)。
#if !__STRICT_ANSI__ && __GNUC__ >= 3
    /* use statement expressions */
#else
    /* use... something else? */
#endif

1

我会像autoconf那样处理这种情况:尝试编译一部分代码,如果编译成功,则在config.h(或其他文件)中输出一个宏定义。

echo 'int main(){ int x = ({ puts(""); 32; }); return x; }' > tmp.c
if cc -c tmp.c; then  #-c only to save on linking time
   echo '#define HAVE_STMT_EXPR 1'
fi

我的玩具项目也依赖于语句表达式。我决定不支持除gcc、clang和tinycc之外的编译器(这三个都有__typeof__和语句表达式)。 - Petr Skocik

1

语句表达式(这似乎是你问题的关键)不是C语言的标准功能。顺便说一下,__typeof__也不是。

这意味着如果你想要类似的功能,最好的策略可能是手动定义宏,允许(或禁止)在代码中使用这些功能。您将手动为那些实现这些非标准功能的特定编译器指定宏。 (基本上只有GCC。)


请注意,标准中使用术语“语句表达式”表示完全不同的意思 - 即用作完整语句的有效表达式。例如:i++; - John Bollinger
@John Bollinger:这个术语应该是“表达式语句”。这是标准使用的术语。同时,“语句表达式”这个术语也可以自由使用 :) - AnT stands with Russia
嗯。你看起来是正确的,但脚注84实际上将“statement expression”用于表达式语句。可以认为这是(非规范性)脚注文本中的一个缺陷。无论如何,如果你要区分这一点,那么我认为你正在创造一个术语。GCC文档似乎没有给这种类型的表达式指定名称。既然如此,我希望你选择一个不容易与“expression statement”混淆的术语。 - John Bollinger
复合表达式? - TripeHound
1
@JohnBollinger:我肯定不是这个术语的发明者。即使GCC有时似乎会偏离这种命名法,但它仍然在GCC文档中广泛使用:https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html(请查看整个文本)。我认为这个术语是由GCC特别创造的,而不是由我创造的。 - AnT stands with Russia

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