Порядок оценки параметров вызова функции в GCC

Когда я гуглил это, у меня всегда были темы о порядке оценки в общем, что порядок оценки не определен.

Я знаю, что порядок оценки параметров не указан в C в общем.

Мой вопрос - порядок оценки параметров в gcc , слева направо или справа налево?

Любые ссылки на ресурсы также будут оценены...

РЕДАКТИРОВАТЬ: устранение двусмысленности в вопросе

Ну, я говорю о ситуации, когда

       foo(1+2,2+3,4+9)

который сначала оценивается?

это 1+2 или же 4+9... как мудрый..

Можем ли мы прийти к объявлению, просто скомпилировав это в одном компиляторе gcc....? или это также отличается в разных версиях gcc?

6 ответов

Решение

Если вы действительно спрашиваете 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))); 
 ...

Так как я ожидал ПЕРВЫЙ (слева) fgetc() называться первым, а вторым fgetc()Я мог бы получить правильное поведение. И это хорошо работало на школьном компьютере. Затем я взял код домой и попытался использовать его на своем домашнем компьютере. И по какой-то причине это не сработало. Мне потребовалось некоторое время, чтобы понять, что foo() просто назывался бесконечно, потому что a никогда не был 'x', который останавливает рекурсию - потому что 'x' никогда не появится во втором вызове.

Это использовало gcc на обеих машинах, но один был sparc (школьный компьютер), а один дома был x86 (386, работающий под OS/2, это как давно).

Решение состоит в том, чтобы разбить его на несколько строк:

 char aa = fgetc(f);
 char bb = fgetc(f);
 foo(aa, foo(bb)); 
#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
// 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());
}

В C++ отсутствует концепция вычисления слева направо или справа налево, что не следует путать с ассоциативностью операторов слева направо и справа налево: выражение f1() + f2() + f3() анализируется как (f1() + f2()) + f3() из-за ассоциативности слева направо оператора +, но вызов функции для f3 может оцениваться первым, последним или между f1 () или f2 () во время выполнения.

Я думаю, что вы объединяете две концепции: 1) порядок оценки параметров (в вызове функции) и порядок вывода аргументов. Во-первых, не определено (зависит от реализации), какие параметры порядка оцениваются перед передачей в функцию. Во втором случае это зависит от соглашения о вызовах для функции, когда cdecl выдвигает аргументы справа налево, а почти все другие соглашения (например, паскаль) - слева направо.

В C механизм передачи параметров основан на стеке, то есть он использует стек (известный как: кадр функционального стека) для хранения параметров, и, следовательно, порядок правильный, потому что Stack - это LIFO . Это было в моем понимании. Пожалуйста, посмотрите на эту ссылку, она объяснит вам больше, я надеюсь, что вы найдете что-то полезное http://zoo.cs.yale.edu/classes/cs427/2012a/resources/Chapter_05.pdf

стр. 55,5.2.3 Механизмы передачи параметров

Другие вопросы по тегам