Порядок оценки параметров вызова функции в 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 Механизмы передачи параметров