GCC中函数调用的参数评估顺序

时间:2013-06-04 16:30:24

标签: c operator-precedence

当我用Google搜索时,我总是得到关于评估顺序的线索,一般说明评估顺序未指定。

我知道参数评估顺序通常在C中未指定。

我的问题是gcc中的参数评估顺序,从左到右还是从右到左?

任何资源链接也将受到赞赏......

编辑:消除问题中的含糊不清

嗯,我说的是

时的情况
       foo(1+2,2+3,4+9)

首先评估?

1+2还是4+9 ......就像明智......

我们可以通过在一个gcc编译器中编译它来获得声明吗?或者它在不同的gcc版本中是否也有所不同?

6 个答案:

答案 0 :(得分:7)

如果你真的问foo(f1(), f2(), f3()) - 这比foo(1+2, 3+4, 5+6)更有意思,因为加上1 + 2和3 + 4无论是先完成还是最后一次或随机抽取都不会有效订购。

现在,不幸的是,您不能依赖于f1()f2()以及f3()以任何特定顺序调用 - 只要每个函数都被称为ONCE,它对订单没问题是任何订单:

   f1, f2, f3
   f1, f3, f2
   f2, f3, f1
   f2, f1, f3
   f3, f2, f1
   f3, f1, f2

(涵盖三个参数的所有排列)。

它完全取决于它“认为最好”的编译器。

我很长一段时间写了一些代码,遇到了这个特殊的问题 - 我有类似的东西:

char foo(char a, char b)
 ... 
 if (a =! 'x')
   foo(fgetc(f), foo(fgetc(f))); 
 ...

由于我期望首先调用FIRST(左)fgetc(),然后调用第二fgetc(),我可以得到正确的行为。它在学校的电脑上运行良好。然后我把代码带回家并尝试在家用电脑上使用它。由于某种原因,它无法正常工作。我花了很长时间才发现foo()只是被无限调用,因为a永远不会'x',这会停止递归 - 因为'x'永远不会出现在第二个电话。

那是在两台机器上都使用gcc,但其中一台是sparc(学校计算机),而家里的那台是x86(386,运行OS / 2,这是多久以前)。

解决方案是将其分成几行:

 char aa = fgetc(f);
 char bb = fgetc(f);
 foo(aa, foo(bb)); 

答案 1 :(得分:2)

#include <stdio.h>

int f1(void){
    printf("In F1\n");
    return 0;
}

int f2(void){
    printf("In F2\n");
    return 0;
}
int f3(void ){
    printf("In F3\n");
    return 0;
}
void f4(int a,int b,int c){
    printf("In F4\n");
    return;
}


int main(){

f4(f1(),f2(),f3());

  getch();
return 0; 
}



output
----------
In F3
In F2
In F1
In F4


but for 
printf("%d..%d..%d",(f1(),f2(),f3()));

output
---------
In F1
In F2
In F3
0..0..0

答案 2 :(得分:0)

我认为你把两个概念混为一谈:1)参数评估的顺序(在函数调用中),以及参数推送的顺序。在第一个中,它是未指定的(依赖于实现)在传递给函数之前评估哪些订单参数。在第二个中,它取决于函数的调用约定,cdecl从右向左推送参数,几乎所有其他约定(例如,pascal)从左向右推送。

答案 3 :(得分:0)

在C ++中没有从左到右或从右到左评估的概念,这不应与运算符的从左到右和从右到左的关联性混淆:表达式f1()由于operator +的从左到右的关联性,+ f2()+ f3()被解析为(f1()+ f2())+ f3(),但是对f3的函数调用可以在第一个,最后一个或之间进行评估运行时f1()或f2()。

答案 4 :(得分:0)

在C中,参数传递机制是基于堆栈的 手段 它使用堆栈(称为:函数堆栈帧)来存储参数,因此订单是正确的,因为堆栈是LIFO。这取决于我的理解。 请看看这个链接,它会更多地解释你,我希望你可以找到一些有用的东西 http://zoo.cs.yale.edu/classes/cs427/2012a/resources/Chapter_05.pdf

第55页 5.2.3参数传递机制

答案 5 :(得分:0)

// according to my tests: left to right for clang-3.4 and right to left
// for gcc-4.8.2
// but don't write any code relying on that: it would be highly unportable

#include <stdio.h>

int one() {
  printf("1\n");
  fflush(stdout);
  return 1;
}

int two() {
  printf("2\n");
  fflush(stdout);
  return 1;
}

int three() {
  printf("3\n");
  fflush(stdout);
  return 1;
}

void test(int a, int b, int c) {
  return;
}

int main() {
  test(one(), two(), three());
}