Mam pytanie, w jaki sposób kompilator działa na następującym kodzie:
#include<stdio.h>
int main(void)
{
int b=12, c=11;
int d = (b == c++) ? (c+1) : (c-1);
printf("d = %i\n", d);
}
Nie jestem pewien, dlaczego wynik jest d = 11
.
Mam pytanie, w jaki sposób kompilator działa na następującym kodzie:
#include<stdio.h>
int main(void)
{
int b=12, c=11;
int d = (b == c++) ? (c+1) : (c-1);
printf("d = %i\n", d);
}
Nie jestem pewien, dlaczego wynik jest d = 11
.
Odpowiedzi:
W int d = (b == c++) ? (c+1) : (c-1);
:
c++
jest bieżąca wartość c
11. Oddzielnie c
zwiększa się do 12.b == 11
jest fałszywe, ponieważ b
ma 12 lat.(b == c++)
jest fałszywe, (c-1)
jest używane. Do c
tego punktu należy również wykonać przyrost o 12.c
ma 12 lat, c-1
ma 11 lat.d
jest inicjowany do tej wartości, 11.Zgodnie ze standardem C (operator warunkowy 6.5.15)
4 Pierwszy argument jest oceniany; między oceną a oceną drugiego lub trzeciego operandu występuje punkt sekwencyjny (w zależności od tego, który jest oceniany). Drugi operand jest oceniany tylko wtedy, gdy pierwszy porównuje nierówny z 0; trzeci argument jest oceniany tylko wtedy, gdy pierwszy porównuje równy 0; wynikiem jest wartość drugiego lub trzeciego operandu (zależnie od tego, który jest oceniany), przekonwertowany na typ opisany poniżej. 110)
Tak więc w inicjującym wyrażeniu tej deklaracji
int d = (b == c++) ? (c+1) : (c-1);
zmienna b
jest porównywana z wartością zmiennej, c
ponieważ operator po inkrementacji zwraca wartość swojego argumentu przed jego inkrementacją.
Ponieważ wartości nie są sobie równe ( b
jest ustawione na 12, podczas gdy c
jest ustawione na 11), wówczas podwyrażenie (c-1)
jest oceniane.
Zgodnie z cytatem istnieje punkt sekwencyjny po ocenie stanu operatora. Oznacza to, że po ocenie warunku c
ma wartość 12
po zastosowaniu operatora po-przyrostowego do zmiennej c
. W rezultacie zmienna d jest inicjalizowana przez wartość 1
( 12 - 1
).
?:
. Ponieważ zwykle w C łączenie ++
z innymi operacjami na tym samym operandzie jest niezdefiniowanym zachowaniem. Ten kod działa tylko przewidywalnie, ponieważ ?:
ma różne specjalne reguły dotyczące płatków śniegu.
Ponieważ warunek jest fałszywy, dlatego false
tak się stanie :, c-1
ale ponieważ zwiększyłeś c
warunek o c++
, dlatego c
jest teraz 12
. Wynik zatem 12 - 1, który wynosi 11.
EDYCJA: To, co OP źle zrozumiał, to przyrost postu.
Tak więc to, co się naprawdę wydarzyło, wygląda następująco:
#include<stdio.h>
int main(void)
{
int b=12, c=11;
int d;
if (b == c) { // 12 == 11 ? -> false
c = c + 1;
d = c + 1;
} else { // this executes since condition is false
c = c + 1; // post increment -> c++ -> c = 12 now
d = c - 1; // 12 - 1 = 11 -> d = 11
}
printf("d = %i\n", d);
}
c++
pod uwagę warunek. Warunek jest fałszywy, ale do obliczenia używana jest wartość oryginalna parametru , a nie wersja przyrostowa. c
c - 1
c++
i++c
c++
jest operatorem post- increment. Wartość c++
wynosi 11, z efektem ubocznym tworzenia c == 12
. ++c
miałby wartość 12.
Patrz operator trójskładnikowy.
Składnia
stan: schorzenie ? wartość_jeśli_prawda: wartość_jeśli_fałsz
Więc napisałeś
int d = (b == c++) ? (c+1) : (c-1);
W tej sytuacji wynikiem będzie 11, ponieważ po sprawdzeniu wartość „c” wzrasta (c + 1 = 12), a dopiero potem ustawia wartość „d” na c (12) -1, która wynosi 11.
Jeśli używałeś na przykład:
int d = (b == ++c) ? (c+1) : (c-1);
Wartość „c” byłaby zwiększona przed sprawdzeniem instrukcji, więc byłaby to prawda, a wartość „d” wynosiłaby c (12) +1, czyli 13.