To (zwróć uwagę na operator przecinka ):
#include <iostream>
int main() {
int x;
x = 2, 3;
std::cout << x << "\n";
return 0;
}
wyjścia 2 .
Jeśli jednak używasz return
z operatorem przecinka, to:
#include <iostream>
int f() { return 2, 3; }
int main() {
int x;
x = f();
std::cout << x << "\n";
return 0;
}
wyjścia 3 .
Dlaczego operator przecinka zachowuje się inaczej z return
?
Odpowiedzi:
Zgodnie z pierwszeństwem operatora , operator przecinka ma niższy priorytet niż
operator=
, więcx = 2,3;
jest równoważny(x = 2),3;
. (Pierwszeństwo operatorów określa, w jaki sposób operator będzie powiązany ze swoimi argumentami, ściślej lub luźniej niż inne operatory, zgodnie z ich priorytetami.)Zwróć uwagę, że wyrażenie z przecinkiem jest
(x = 2),3
tutaj, a nie2,3
.x = 2
jest najpierw oceniany (a jego skutki uboczne są zakończone), następnie wynik jest odrzucany, a następnie3
oceniany (w rzeczywistości nic nie robi). Dlatego wartośćx
jest2
. Zauważ, że3
jest to wynik całego wyrażenia z przecinkiem (tj.x = 2,3
), Nie będzie ono używane do przypisywaniax
. (Zmień nax = (2,3);
,x
zostanie przypisany3
.)Ponieważ
return 2,3;
wyrażenie z przecinkiem jest2,3
,2
jest oceniane, a następnie jego wynik jest odrzucany, a następnie3
oceniany i zwracany jako wynik całego wyrażenia z przecinkiem, które jest później zwracane przez instrukcję return .Dodatkowe informacje o wyrażeniach i instrukcjach
x = 2,3;
jest wyrażeniem ,x = 2,3
jest wyrażeniem tutaj.return 2,3;
jest instrukcją skoku ( instrukcją powrotu ),2,3
jest wyrażeniem tutaj.źródło
for
pętlach, kiedy, co dziwne, może uczynić kod wyraźniejszym w obliczeniach numerycznych.i += 1, j += 2
w rodzaju pętli for. Ktoś zdecydował, że gramatyka C ++ (a raczej gramatyka C, ponieważ ta część została skopiowana stamtąd) jest już wystarczająco skomplikowana bez próby zdefiniowania, że pierwszeństwo przecinka jest wyższe niż przypisanie podczas pisania,x = 2, 3
ale niższe podczas pisaniax = 2, y = 3
!Operator przecinka (znany również jako separacja wyrażenia ) jest oceniany od lewej do prawej. Więc
return 2,3;
jest równoważnereturn 3;
.Ocena
x = 2,3;
jest(x = 2), 3;
ze względu na pierwszeństwo operatora . Ocena jest nadal od lewej do prawej, a całe wyrażenie ma wartość 3, czego skutkiem ubocznym jestx
przyjęcie wartości 2.źródło
return 2,3
ireturn (2,3)
są takie same. Uważałem, że to pierwsze powinno być(return 2),3
.return 2
to instrukcja (jak np. utworzone przezfor,while,if
), a nie wyrażenie. Nie możesz pisać np .f(return 2)
Lub2+return 2
. Więc(return 2),3
jest niepoprawna składniowo.return 2, 3
się, że będę interpretowany jako(return 2), 3
.return
może wystąpić tylko w następujących przypadkach: (a)return
expression_opt;
i (b)return
braced-init-list;
.To oświadczenie:
x = 2,3;
składa się z dwóch wyrażeń :
> x = 2 > 3
Ponieważ pierwszeństwo operatorów ,
=
ma wyższy priorytet niż przecinek,
, więcx = 2
jest oceniany i po3
. Wtedyx
będzie równy2
.W
return
zamian:int f(){ return 2,3; }
Składnia języka to:
return <expression>
Uwaga
return
nie jest częścią wyrażenia.Więc w tym przypadku dwa wyrażenia zostaną ocenione:
> 2 > 3
Ale tylko druga (
3
) zostanie zwrócona.źródło
<expression>
jako wyraźnie opcjonalny (z punktu widzenia gramatyki).x=2,3
. Oba literały2
i3
znajdują się na dole drzewa analizy, podobnie jak identyfikatorx
. Są to wyrażenia ważne indywidualnie. Środki operator pierwszeństwa że=
występuje niższy w drzewie parsowania, i łączy w sobie dwa wyrażeniax
i2
do czwartego wyrazux=2
. Wreszcie, piąte wyrażenie jest tworzone przez operator przecinka łączący jego dwie stronyx=2
i3
. Jednak niepoprawnie określasz, że pierwszeństwo operatorów określa kolejność oceny. Tak nie jest. Kolejność oceny jest określana przez zasady sekwencjonowania.Spróbuj zastosować uproszczone podejście, podkreślając pierwszeństwo nawiasami:
( x = 2 ), 3;
return ( 2, 3 );
Teraz widzimy operator binarny "," działający w ten sam sposób na obu, od lewej do prawej.
źródło
x = 2, 3
samo jest wyrażeniem, podczasreturn
gdy jestreturn <expression>
. Więc czytasz je jako(x = 2, 3)
i(2, 3)
.