【问题标题】:Function call in if statement without parentheses不带括号的 if 语句中的函数调用
【发布时间】:2012-10-02 15:05:51
【问题描述】:

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,这并不完全正确,因为 C 语法在此特定上下文中需要括号。恰好这里的括号是由宏提供的。
  • Jelle,这就是为什么我说“这是一种有趣的表达方式”,因为据我所知,括号是必需的。

标签: c syntax


【解决方案1】:

islower() 很可能是一个宏,并且扩展添加了括号。

发布来自 GCC 的预处理输出,您可以通过使用 -E 选项进行编译来获得。

【讨论】:

    【解决方案2】:

    我刚刚查看了位于/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)”。
    猜你喜欢
    • 2012-07-02
    • 2017-06-14
    • 2015-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多