在if语句中调用函数时没有使用括号

7

最近在 Fedora Linux 上,gcc 和 clang 的版本可以编译以下程序而不出现错误:

#include <ctype.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
    char c = 'a';
    if islower(c)
        printf("%d", c);
    else
        printf("%c", c);
    return 0;
}

这是使用gcc 4.7.2和clang 3.0进行的。在我的Mac上,相反,gcc 4.2.1和Apple clang 4.1都会抱怨“if islower(c)”行缺少括号,这是预期的。在所有情况下,我都使用“-std=c99”运行编译器。
这是最近版本的gcc和clang中的一个错误、C语言的怪癖还是其他原因? C99标准(http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf p. 133)似乎要求在所有情况下都要在if表达式周围加上括号。

它会编译吗?if 42 printf("42!\n"); 如果可以,那么这是表达式的有趣用法。正式地说,如果我们忽略 if42(42) 是相同的。对于 islower(c)(islower(c)) 也是如此。 - Alexey Frunze
Alexey,这并不完全正确,因为C语法在这种特定的上下文中需要括号。恰好在这里,括号是由宏提供的。 - Jelle Zijlstra
Jelle,这就是为什么我说“这是表达式的有趣方式”,因为据我所知,括号是必需的。 - Alexey Frunze
2个回答

13

很可能islower()是一个宏,而展开时添加了括号。

您可以使用-E选项编译以获得GCC的预处理输出。


10

我刚刚查看了位于/usr/include/ctype.hctype.h文件,并找到了islower的以下定义:

#define islower(c)  __isctype((c), _ISlower)

查看__isctype()的定义,我发现:

#define __isctype(c, type) \
  ((*__ctype_b_loc())[(int) (c)] & (unsigned short int) type)

所以你的代码 if islower(c) 扩展为:

if ((*__ctype_b_loc())[(int) (c)] & (unsigned short int) _ISlower)

正如unwind所说,它在展开过程中添加了括号。


放松一下,你是对的,谢谢!我应该猜到那就是情况了。 如你所言,gcc -E生成了"if ((*__ctype_b_loc ())[(int) ((m))] & (unsigned short int) _ISalpha)"。 - Jelle Zijlstra

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