Bitweise XOR-Zuweisung ^=

Der Bitweise-XOR-Zuweisungs-Operator verknüpft den Wert, der rechts des Operators steht mit dem Wert der links des Operator stehenden Variablen mittels dem bitweisen-XOR-Operator und speichert das Resultat zurück in die Variable.

#include <stdio.h> void printbinary(int x){ char str[33]; str[32] = '\0'; int i = 32; while(i){i--; str[i] = (x & 1) + '0'; x>>=1;} printf("%s\n", str); } int main(){ int a = 1234567890; printbinary(1234567890); printbinary(987654321); a ^= 987654321; printbinary(a); }

01001001100101100000001011010010 00111010110111100110100010110001 01110011010010000110101001100011

Siehe auch Zuweisungs-Operator =, Bitweise-XOR-Operator ^

Details

Der Bitweise-XOR-Zuweisungs-Operator erwartet links einen lvalue und rechts einen rvalue und wird von rechts nach links abgearbeitet. Der Rückgabewert ist in C ein rvalue: Der Wert des linken Operanden nach der Zuweisung. in C++ ist der Rückgabewert ein lvalue: Der (mittlerweile zugewiesene) linke Operand selbst.

Der Bitweise-XOR-Zuweisungs-Operator verhält sich genau gleich wie der Zuweisungsoperator, nur dass er eine zusätzliche XOR-Verknüpfung ausführt. Für Details über die Eigenschaften einer Bitweise-XOR-Zuweisung wird hier somit auf die Beschreibung des Zuweisungsoperators und des Bitweise-XOR-Operators verwiesen. Als zusätzliche Erläuterung des Bitweise-XOR-Zuweisungs-Operators im Bezug zum einfachen Zuweisungsoperator genügen folgende zwei Programmzeilen, welche absolut äquivalent sind:

a ^= 10; a = a ^ (10);

Die gesetzten runden Klammern deuten an, dass aufgrund der Operatoren-Rangordnung bei der Bitweise-XOR-Zuweisung genauso wie bei allen Zuweisungs-Operatoren der komplette rechte Teil nach den Gleichheitszeichen als EIN Operand ausgewertet wird.

Überladen des Operators

Der Bitweise-XOR-Zuweisungs-Operator hat grundsätzlich die semantische Bedeutung einer bitweisen XOR-Verknüpfung mit einem Wert und anschliessender Zuweisung des Resultates zur Variablen. Allerdings steht es dem Programmierer frei, eine andere Semantik zu definieren. Da das Zeichen ^ in vielen Sprachen als Potenzierungs-Zeichen (Power-Operator) verwendet wird, würde sich die Ausprogrammierung einer Potenz-Funktion anbieten. in C und C++ wird eine solche Semantik jedoch nach allgemeinem Bewusstsein mit einer Funktion mit dem Namen pow ausprogrammiert, weswegen hier explizit von einer solchen Verwendung des Operators abgeraten wird.

Die Prototypen für das Überladen des Bitweise-XOR-Zuweisungs-Operators sind die folgenden (Einschränkungen und Erläuterungen siehe Überladen von Operatoren):

Type operator |=(Type); Type operator |=(Type) const; Type operator |=(Type, Type);

inside class outside class

Man beachte, dass der Bitweise-XOR-Zuweisungs-Operator im Gegensatz zum einfachen Zuweisungs-Operator sowohl innerhalb als auch ausserhalb der Klasse überladen werden kann, obschon gewisse Quellen dies nicht erlauben. Es ist jedoch grundsätzlich zu empfehlen, Zuweisungs-Operatoren nicht ausserhalb der Klasse zu definieren.

Da der Bitweise-XOR-Zuweisungs-Operator in C++ normalerweise einen lvalue zurückgibt, ist der Rückgabetyp der Überladung üblicherweise ein Referenz-Typ (&) der eigenen Klasse, wobei der Rückgabewert normalerweise mit return *this angegeben wird.

Der const-Prototyp macht auf den ersten Moment keinen Sinn, da bei einer Zuweisung im herkömmlichen Sinne das betroffene Objekt immer verändert wird. Man beachte jedoch, dass Felder von Klassen mittels der mutable-Speicherklasse deklariert werden können, was es ermöglicht, einen Bitweise-XOR-Zuweisungs-Operator als konstant zu deklarieren. Bei Auftreten beider Prototyp-Varianten in einer Klasse wird jedoch grundsätzlich (ohne die Notwendigkeit eines const-Aufrufes) die nicht-const-Überladung aufgerufen.

Im folgenden Beispiel wird eine Klasse für einen fiktiven Prozess präsentiert. Der überladene Bitweise-XOR-Zuweisungs-Operator wechselt ein Flag (auf Englisch switching) für den Status des Prozesses.

#include <cstdio> typedef enum{ VALID = 0x01, RUNNING = 0x02, ERROR = 0x04, } Status; class Process{ int state; public: Process() : state(VALID){} void printstatus(){ if(state & VALID){printf("valid ");} if(state & RUNNING){printf("running ");} if(state & ERROR){printf("error ");} printf("\n"); } Process& operator ^=(Status flag){ state ^= flag; return *this; } }; int main(){ Process p; p.printstatus(); p ^= RUNNING; p.printstatus(); p ^= RUNNING; p.printstatus(); return 0; }

valid valid running valid