将常量定义为printf格式参数,为什么添加“+ 0”?

时间:2017-01-05 01:28:14

标签: c

我正在读一本关于C编程的书“在Unix环境中进行高级编程”,在“ UNIX标准化和实现”一章中它显示了一个打印的程序sysconf和pathconf中符号的值,此程序中的代码有几行,如下所示:

#ifdef ARG_MAX
    printf ("ARG_MAX defined to be %ld\n", (long) ARG_MAX + 0);
#else
    printf ("no symbol for ARG_MAX\n");
#endif

每当定义的常量被用作printf的参数时,它始终跟在+ 0之后,它似乎没有做任何事情,因为我试图删除它并且什么都没发生。添加零点有什么意义?

2 个答案:

答案 0 :(得分:9)

melpomenecomment提到的空#define是使用+ 0技巧的原因。

如果某个标题有#define ARG_MAX(没有值) - 一个不太可能但不是不可能的事态 - 代码仍会编译,但输出是否有用是一个单独的讨论。 ARG_MAX的空白替换为[{1}},但仍然有效。如果,正如您所期望的那样,定义是一个受适当保护的表达式(可能在括号内),添加(long) + 0不会更改该值。

在正常的事件过程中,当预处理器评估条件表达式时,扩展宏之后遗留的任何标识符都映射为零(ISO / IEC 9899:2011§6.10.1条件包含):

  

¶4...由于宏扩展和0一元的所有替换后   运算符已执行,所有剩余的标识符(包括那些词法   用关键字替换为pp-number 0,然后进行每次预处理   令牌转换为令牌。 ...

虽然这与此问题没有直接关系,但 为什么有时会看到条件表达式,例如:

defined

答案 1 :(得分:0)

这是因为该代码是从awk程序自动生成的。

  

图2.12中显示的awk(1)程序构建了一个C程序,用于打印每个pathconf和sysconf符号的值。

该计划的重要部分是这个。

while (getline <"sysconf.sym" > 0) {
    printf("#ifdef %s\n", $1)
    printf("\tprintf(\"%s defined to be %%d\\n\", %s+0);\n", $1, $1)
    printf("#else\n")
    printf("\tprintf(\"no symbol for %s\\n\");\n", $1)
    printf("#endif\n")
    printf("#ifdef %s\n", $2)
    printf("\tpr_sysconf(\"%s =\", %s);\n", $1, $2)
    printf("#else\n")
    printf("\tprintf(\"no symbol for %s\\n\");\n", $2)
    printf("#endif\n")
}

由于它不知道符号可能含有什么,它可能对此有所防御,尽管这本书并没有解释它的防御性。