【问题标题】:Expanded from macro 'num' while printing it using printf by Clang compiler在使用 Clang 编译器的 printf 打印时从宏“num”扩展
【发布时间】:2015-08-07 12:04:25
【问题描述】:

代码:

char *color_name[] = {
    "red",
    "blue",
    "green"
};

#define color_num (sizeof(color_name)/sizeof(char*))

int main(){
    printf("size %d \n",color_num);
    return 0;
}

它可以在 Centos 7 上与 GCC 4.8.2 一起正常工作。

但我在 mac 上运行上面的程序时出错:

note:expanded from macro 'color_num'

我的 Mac 上的编译器:

……include/c++/4.2.1
Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.3.0
Thread model: posix

听说 GCC 在 Mac 上用于编译程序时已链接到 Clang,对吗?

问题:

那么为什么 Clang 会报告这个错误呢?这与预处理有关吗?

如果我这样做,它工作正常:

int a = color_num;
printf("%d\n",a);

或:

printf("%d\n",sizeof(color_num)/sizeof(char*));

UPDATA=============

Crayon_277@Macintosh 20150525$ gcc -g -o ex11 ex1.c
ex1.c:16:21: warning: format specifies type 'int' but the argument has type 'unsigned long' [-Wformat]
        printf("size %d\n",color_num);
                     ~~    ^~~~~~~~~
                     %lu
ex1.c:14:19: note: expanded from macro 'color_num'
#define color_num (sizeof(color)/sizeof(char*))
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.

似乎没有错误,只是那个格式警告。

我认为这可能与我用于 vim 的扩展有关 scrooloose/语法

我得到了错误:

【问题讨论】:

  • 如果您可以发布实际的错误消息会有所帮助。 “注释”只是为了帮助您理解错误,而不是错误消息本身。
  • 这是意料之中的。实际上,gcc 也会通知这一点,但它确实需要包含在 -Wall 中的 -Wformat。后者是至少应该始终启用的(-Wextra 推荐)。
  • 请注意,没有参数的函数应注明f(void)

标签: c gcc macros clang c-preprocessor


【解决方案1】:

这可能是抱怨从color_num 扩展的表达式是无符号的(可能是无符号长的),而 printf 中的格式是有符号整数。

sizeof 给出size_t,它始终是无符号类型,如is size_t always unsigned? 中所述,但位数取决于实现。编译器警告可能(并且经常这样做)以等效类型而不是 size_t 的形式引用不匹配。毕竟 C 标准并没有指定诊断消息的性质。

当您将其更改为分配时,它不那么严格,因为这是不同的检查。

“注释”行是编译器添加到警告/错误消息中的内容,以帮助您了解问题的根源。

(正如评论所指出的,您应该引用整个警告信息,以使问题易于理解)。

【讨论】:

  • sizeof 返回 size_t;将它实际映射到的内容留给工具链。
  • @Olaf 它不返回任何内容,它是一个运算符,它在编译时进行评估。
  • Thomas:参考标准:n1570, 6.5.3.4/5 即可。对于赋值 - 与任何其他表达式一样 - 应用默认强制规则。但是,gcc 至少可以(并且应该)也能够警告其中一些(例如 -Wconversion)。
  • @iharob:VLA 怎么样?无论如何,每个运算符实际上都是一个函数,它接受参数并返回一个结果。例如,sizeof 与一元“-”没有什么不同。请注意,评估时间不会改变这一点。该标准很好地允许编译器在编译时评估一个函数,如果它可以证明它是常量/纯的。它实际上确实如此:只考虑表达式。请注意,标准明确提到它“产量”(6.5.3.4/2,也适用于 VLA)。对于 C,我认为它是一样的;但这里不讨论“收益”和“回报”的区别
【解决方案2】:

sizeof 给出size_t 类型的值,size_t 的正确格式说明符是"%zu"

【讨论】:

    猜你喜欢
    • 2014-03-07
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多