使用printf时使用双括号时出现分段错误

#include<stdio.h> #define POOLNAME_FMT "Hello" void main() { printf((POOLNAME_FMT "Cannot allocate %d bytes" POOLNAME_FMT "in pool not enough memory",5)); } 

为什么当我在printf使用双括号的时候会出现分段错误 。 即printf(( ));

因为(a, b)实际上是一个单一的值。 它计算ab并返回b的值。

所以你在做什么基本上是:

 /* calculate before `,` and ignore */ POOLNAME_FMT "Cannot allocate %d bytes" POOLNAME_FMT "in pool not enough memory"; /* call printf with after `,` */ printf(5); 

这显然是错误的。


当你把func(a, b)写成函数调用的时候,C知道把ab作为独立的参数发送给func 。 当你说func((a, b)) ,你明确地说(a, b)一个值,结果(即b的值)应该作为单个参数发送给func

如果你编译时有警告,如果你的编译器对你很好,它可能会提醒你。 如果你的编译器不好,它应该仍然抱怨你给一个int const char *所期望的。

如果使用gcc ,我强烈推荐使用-Wall编译。

您正在使用逗号运算符而没有意识到:

 ( ... "in pool not enough memory",5) ^ 

由于逗号运算符将评估其左操作数并放弃结果,然后评估并返回右操作数,则最终将得到:

 printf( 5 ) ; 

它将尝试将int转换为格式字符串的const char *restrict ,这几乎肯定不会指向有效的内存。 如果没有() ,那么这个函数参数就是分隔符。

()是这个上下文中的表达式; 如果我们看看C99草案标准部分6.5.1 主要表达式 ,我们有:

 ( expression ) 

因此,我们可以从6.5.2节看到,作为运算符。 后缀运算符

 postfix-expression ( argument-expression-listopt ) argument-expression-list: assignment-expression argument-expression-list , assignment-expression ^ 

这只是函数调用中的分隔符。

启用警告应该有帮助, gcc给了我这个程序的一些警告:

警告:逗号表达式的左侧操作数不起作用[-Wunused-value]

警告:传递'printf'的参数1使得整型指针没有转换[默认情况下启用]注意:期望'const char * restrict',但参数的类型是'int'

这是因为printf是一个函数,它将在单个括号中接受它的参数,而第二个parenthess实际上是打开一个子表达式:

 (string "string" string "string" , 5) 

前四个字符串在编译时连接在一起,产生:

 ("string", 5) 

然后评估:

  • "string"计算结果是一个指向它的第一个字符的指针
  • a , b先评估一个 ,然后抛出结果,然后评估和返回b
  • 5评估为一个整数常数5

所以实际上,你打电话给:

 printf(5); 

(这是因为字符串没有副作用。)

然而,像这样的东西可以工作:

 printf((POOLNAME_FMT "Cannot allocate %d bytes" POOLNAME_FMT "in pool not enough memory"),5); 

注意逗号和五个是如何移到括号内的子表达式之外的。