C - 将双括号与 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 运算符中看到:

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

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

启用警告应该在这里有所帮助,gcc为该程序提供了一些警告:

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

警告:传递"printf"的参数 1 会使指针从整数变为不带强制转换的指针 [默认启用]     注意:预期的"常量字符 * 限制",但参数的类型为"int">

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

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

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

("string", 5)

然后对此进行评估:

  • "string"计算结果为指向其第一个字符的指针
  • A , B 首先计算 a,然后丢弃结果,然后计算并返回 b
  • 5计算结果为整数常量 5

因此,实际上,您正在调用:

printf(5);

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

但是,这样的事情会起作用:

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

请注意逗号和五号是如何移动到括号子表达式外部的。

相关内容

  • 没有找到相关文章