C-在printf中使用堆栈;GCC未指定的行为



当我们在单个printf中使用多个分配时,会发生什么?当然,这是一种未指定的行为。但是,GCC的表现如何?(我希望这种行为是GCC版本的独立性)

示例:

int a=30;  
printf("%d %d %d %d",a=12,a++,a=a+1); 

上述代码段给出了输出
12 31 12

a=30;  
printf(" %d %d %d %d ",a--,a=12,a++,a=a+1); 

给出输出
12 11 31 11

a=30,b=100;  
printf("%d %d %d %d  %d %d %d %d ",a=12,b++,a++,a=200,b=20,a++,a=a+2,b=40); 

给出输出
12 20 200 12 21 32 12 21

a=30,b=100;  
printf("<outside>(%d chars for inside printf) %d %d %d %d ",  
printf("<inside> %d %d %d %d ",a=12,b++,a++,a=200),b=20,a++,a=a+2,b=40);  

给出输出
12 20 200 12(内部printf的22个字符)21 32 12 21

我们发现的解释是对左右进行评估,分配为每个变量的最终值,而其他表达式似乎将其推向堆栈?这是一个很好的解释,还是其他事情正在发生?

(NB:GCC可能使用某些寄存器而不是堆栈。但是行为似乎相同)

我的老师解释说每个变量都有一个管道,当%d冲洗管道时,其内容不会丢失。因此,当该变量再次由另一%d采用时,再次使用管道的旧内容。

注释:提前和续报的态度被视为分配,而后的提议和后期则被视为"其他表达"。

no,它是不是未指定的,它是 undefined行为

您本质上试图在没有序列之间的序列点上多次修改单个变量的值。那就是它击中UB的地方。

fwiw,不能保证使用堆栈传递函数参数。它们很可能通过登记册通过。而且,C标准中提到的"堆栈"one_answers"堆"等没有继承的概念,因此结论本身的前提不是普遍有效的。

故事的道德:启用编译器警告并将警告视为错误,任何体面的编译器都应拒绝编译如上所述。

这是一种不确定的行为,不确定的行为意味着任何事情都可能发生。

根据此博客:

C FAQ定义了这样的"未定义行为":

任何事情都可能发生;该标准没有任何要求。该程序可能无法编译,或者可能执行错误(要么 崩溃或默默产生错误的结果),或者可能 幸运地做程序员的意图。

我使用gcc -Wall标志在Linux平台上 gcc 编辑了您的程序,我得到了警告:

seq.c:6:32: warning: operation on ‘a’ may be undefined [-Wsequence-point]
  printf("%d %d %dn",a=12,a++,a=a+1);
                                ^
seq.c:6:32: warning: operation on ‘a’ may be undefined [-Wsequence-point]

在哪个顺序它将评估,这是在C标准中未定义的。

最新更新