C printf()中以逗号分隔的表达式会产生意外结果

C printf()中以逗号分隔的表达式会产生意外结果,c,printf,assignment-operator,C,Printf,Assignment Operator,如果太显眼的话,我很抱歉,但我这里有点模糊。 我编写了以下代码: #include <stdio.h> int main() { int a = 8 , b = 7 ; int temp; printf("%d\n", temp=a,a=b,b=temp); return 0; } #包括 int main(){ INTA=8,b=7; 内部温度; printf(“%d\n”,temp=a,a=b,b=temp); 返回0; }

如果太显眼的话,我很抱歉,但我这里有点模糊。

我编写了以下代码:

#include <stdio.h>
int main() {
    int a = 8 , b = 7 ;
    int temp;
    printf("%d\n", temp=a,a=b,b=temp);
    return 0;
}
#包括
int main(){
INTA=8,b=7;
内部温度;
printf(“%d\n”,temp=a,a=b,b=temp);
返回0;
}
它发出了警告 输出:
0


根据我的说法,输出应该是
8
,因为我尝试过这种代码
printf(“%d”,a,b)它打印a的值,这使我得出一个结论,即第一个表达式将打印一个警告,警告格式的参数过多。
因此,在我的例子中,当
temp=a
必须是答案,因此应该打印变为
8
的temp值。

请解释一下,我哪里做错了?

提前感谢您从以下地址提供的任何帮助:

【重点已添加】

任何C运算符的操作数的求值顺序,包括函数调用表达式中函数参数的求值顺序,并且任何表达式中子表达式的求值顺序为未指定的(以下说明除外)。编译器将以任何顺序对它们求值,并且当再次对同一表达式求值时,可以选择另一个顺序

因为函数参数的求值顺序未指定。传递给
printf()
的参数包括对同一变量的读取和写入,并且没有序列点,这将导致错误

来自C标准#6.5p2

2如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量对象的值进行的值计算未排序,则行为未定义


编辑 如果将逗号作为运算符和逗号作为分隔符混淆,则逗号是函数参数列表中的分隔符

引用C标准#6.5.17p3中的示例以供参考

3如语法所示,逗号运算符(如本款所述)不能出现在使用逗号分隔列表中的项目(如函数参数或初始值设定项列表)的上下文中。另一方面,在这样的上下文中,它可以在带括号的表达式中使用,也可以在条件运算符的第二个表达式中使用。在函数调用中

该函数有三个参数,第二个参数的值为5

在上述示例中:

     Here comma is operator, so the expression will be evaluated to 5 (3+2)
         |
         | 
f(a, (t=3, t+2), c)
   |           |
   |           |
   -------------
        |
   here, comma is separator
发件人:[强调添加]

任何C运算符的操作数的求值顺序,包括函数调用表达式中函数参数的求值顺序,并且任何表达式中子表达式的求值顺序为未指定的(以下说明除外)。编译器将以任何顺序对它们求值,并且当再次对同一表达式求值时,可以选择另一个顺序

因为函数参数的求值顺序未指定。传递给
printf()
的参数包括对同一变量的读取和写入,并且没有序列点,这将导致错误

来自C标准#6.5p2

2如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量对象的值进行的值计算未排序,则行为未定义


编辑 如果将逗号作为运算符和逗号作为分隔符混淆,则逗号是函数参数列表中的分隔符

引用C标准#6.5.17p3中的示例以供参考

3如语法所示,逗号运算符(如本款所述)不能出现在使用逗号分隔列表中的项目(如函数参数或初始值设定项列表)的上下文中。另一方面,在这样的上下文中,它可以在带括号的表达式中使用,也可以在条件运算符的第二个表达式中使用。在函数调用中

该函数有三个参数,第二个参数的值为5

在上述示例中:

     Here comma is operator, so the expression will be evaluated to 5 (3+2)
         |
         | 
f(a, (t=3, t+2), c)
   |           |
   |           |
   -------------
        |
   here, comma is separator

问题不是初始化温度。 表达式“b=temp” 将返回一个错误。 结果有8个

printf("%d\n", temp = b, b = a)
您可以计算代码,只需在printf中使用一个变量

编辑
根据答案,您不能说评估是从右到左的,因为它是未定义的。

问题不是初始化temp。 表达式“b=temp” 将返回一个错误。 结果有8个

printf("%d\n", temp = b, b = a)
您可以计算代码,只需在printf中使用一个变量

编辑
根据答案,您不能说评估将从右向左,因为它是未定义的。

H.S.的答案是正确的,C语言规范中未指定参数的评估顺序。参数可以按任何顺序进行评估

比较常见的是,计算顺序通常是向后的(从最右边的参数到第一个参数)。这是因为堆栈上参数顺序的细节

我们可以推断参数的计算方式如下:

  • b=temp
    ::
    temp
    未定义,但可能为零,因此
    b
    可能为零
  • a=b
    :如果
    b
    为零,则
    a
    现在为零
  • temp=a
    ::
    temp
    被分配了
    a
    的值,该值可能为零,但可能是
    temp
    的未初始化值。这是
    printf
    用于格式化
    %d
    的参数。未使用额外的参数(可能会生成警告)
  • “%d\n”
    ::这里没有太多要计算的内容,只是一个静态字符串
  • 虽然输出可以是任何东西
    printf("%d\n", (temp = a, a = b, b = temp));
    //                      ^      ^ comma operator
    //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1 argument grouped