Mam następujący kod:
#include <stdio.h>
int main(int argc, char **argv) {
int i = 0;
(i+=10)+=10;
printf("i = %d\n", i);
return 0;
}
Jeśli spróbuję skompilować go jako źródło C przy użyciu gcc, pojawia się błąd:
error: lvalue required as left operand of assignment
Ale jeśli skompiluję go jako źródło C ++ przy użyciu g ++, nie otrzymuję błędu, a kiedy uruchomię plik wykonywalny:
i = 20
Skąd to inne zachowanie?
Odpowiedzi:
Semantyka operatorów przypisania złożonego jest inna w C i C ++:
Standard C99, 6.5.16, część 3:
W C ++ 5.17.1:
EDYCJA: zachowanie
(i+=10)+=10
w C ++ jest niezdefiniowane w C ++ 98, ale dobrze zdefiniowane w C ++ 11. Zobacz tę odpowiedź na pytanie NPE dla odpowiednich części norm.źródło
(i+=10)+=10
jest to niezdefiniowane zachowanie w C ++, zobacz odpowiedź @aix.int f(int &y); f(x += 10);
- przekazanie odniesienia do zmodyfikowanej zmiennej do funkcji.Oprócz tego, że jest nieprawidłowym kodem C, wiersz
spowodowałoby niezdefiniowane zachowanie zarówno w C, jak i C ++ 03, ponieważ zmieniłoby się
i
dwukrotnie między punktami sekwencji.Dlaczego można kompilować w C ++:
Ten sam akapit mówi o tym
Sugeruje to, że w C ++ 11 wyrażenie nie ma już niezdefiniowanego zachowania.
źródło
i
które nie są sekwencjonowane.i = j+=1
, skutkowałoby to nieokreśloną wartością. Z tego samego akapitu, który cytujesz: „We wszystkich przypadkach przypisanie jest sekwencjonowane po obliczeniu wartości prawych i lewych operandów, a przed obliczeniem wartości wyrażenia przypisania”. Dlatego(i+=10)+=10
jest dobrze zdefiniowany do zrobieniai += 10; i += 10;
. Z drugiej strony(i+=10)+=(i+=10)
jest UB.