Kolejność oceny ^=
operatorów jest dobrze zdefiniowana. To, co nie jest dobrze zdefiniowane, to kolejność modyfikacji a
i b
.
a ^= b ^= a ^= b;
jest równoważna
a ^= (b ^= (a ^= b));
Operator nie może być oceniane przed jej argumenty są oceniane, więc na pewno będzie wykonać a ^= b
pierwszy.
Przyczyną tego zachowania jest niezdefiniowanie, ponieważ w celu zapewnienia kompilatorowi większej elastyczności w dokonywaniu optymalizacji dozwolona jest modyfikacja wartości zmiennych w dowolnej kolejności.To może wybrać to zrobić:
int a1 = a^b;
int b1 = b^a1;
int a2 = a^b1;
a = a1;
a = a2;
b = b1;
lub to:
int a1 = a^b;
int b1 = b^a1;
a = a1;
int a2 = a^b1;
a = a2;
b = b1;
lub nawet poniżej:
int a1 = a^b;
int b1 = b^a1;
int a2 = a^b1;
a = a2;
a = a1;
b = b1;
Jeśli kompilator mógł wybrać tylko jedną z tych trzech sposobów, aby robić rzeczy, byłoby to po prostu "nieokreślone" zachowanie. Jednak standard idzie dalej i sprawia, że jest to zachowanie "niezdefiniowane", które zasadniczo pozwala kompilatorowi zakładać, że nawet nie może się zdarzyć.
Jeśli piszesz kod, który jest trudny do określenia, co się dzieje, zadaj sobie pytanie, czy istnieje bardziej prosty sposób, który może zrozumieć przyszły programista? –
Zauważ, że jeśli widziałeś to w C++, C++ ma różne reguły dla operatorów przypisania, które zezwalają na pewne konstrukcje (nie jestem tego pewien), które są niezdefiniowane w C. – hvd
możliwy duplikat [Sequence Point - Xor Zamień na Array otrzymasz zły wynik] (http://stackoverflow.com/questions/9958514/sequence-point-xor-swap-on-array-get-wrong-result) –