cdecl函数的参数处理顺序

问题描述 投票:0回答:2

据我所知,

cdecl
函数将其参数从右到左压入堆栈。然而,

int n = 0;
printf("%d %d", n=8, n); // Output: 8 8

我希望它输出

8 0
,因为我认为它按照从右到左推送参数的顺序来计算参数。我在
TDM-GCC 32bit/64bit
GCC x64
MSVC x86/x64
clang x64
上尝试了代码,得到了相同的结果。

所以我得出的结论是,

cdecl
函数在将参数压入堆栈之前计算其参数,并且两个过程以相反的顺序进行。

但是,

int n = 0;
printf("%d %d", n=8, n=0); // Output: 8 8

我不明白。

c printf cdecl
2个回答
0
投票

在 C 中,函数参数的求值顺序是未指定的。这意味着编译器可以按照它选择的任何顺序自由地计算参数。这是理解的关键点。参数压入堆栈的顺序(在 cdecl 调用约定的情况下)不一定与它们求值的顺序相同。

printf("%d %d", n=8, n);

这里,由于未指定参数的求值顺序,因此 n=8 和 n 都可以按任何顺序求值。大多数编译器从左到右评估函数参数,但 C 标准不保证这一点。在你的例子中,似乎首先评估 n=8,将 n 设置为 8。然后,当评估 n 时,它已经是 8。因此,你会看到 8 8。

printf("%d %d", n=8, n=0);

这个案例和第一个案例类似。未指定的参数求值顺序导致两个赋值都可能以任意顺序求值。如果首先计算 n=8,则 n 设置为 8,然后 n=0 可能不会更改输出,因为 printf 可能已经获取了第一个 %d 的 n 值。此行为可能因不同的编译器甚至同一编译器的不同版本而异。


0
投票

C 语言中没有定义求值顺序。

您的示例打印

8 8
很可能是因为编译器已经优化了分配,并且它可以像 UB 一样执行此操作。

如果无法完成此优化,下面的示例将显示不同的行为(这取决于编译器,因为它是 UB) .

int main(void)
{
    volatile int n = 0;
    int m = 0;
    printf("n= %d %d\n", n = 8, n);
    printf("m= %d %d\n", m = 8, m);
}

https://godbolt.org/z/crKbs1hjE

© www.soinside.com 2019 - 2024. All rights reserved.