C++: Warum kein xor auf Pointer?

Gast #5058357
Lesenswert?

Hallo Forum,

um 2 Werte zu tauschen kann man sich eine extra Variable anlegen, oder 
aber die beiden Werte per xor tauschen (spart die extra Variable).
1
int a = 5;
2
int b = 7;
3

4
a = a ^ b;
5
b = a ^ b;  //  b = 5
6
a = a ^ b;  //  a = 7

Warum genau ist die xor-Operation auf Pointer nicht zulaessig?
1
int a = 5;
2
int b = 7;
3
    
4
int *x = &a;
5
int *y = &b;
6

7
x = x ^ y;
8
y = x ^ y;  //  y = &a
9
x = x ^ y;  //  x = &b
1
invalid operands of types 'int*' and 'int*' to binary 'operator^'

C++, GCC 7.1.1


Die Sinnhaftigkeit sei mal dahingestellt. Mich interessiert nur, warum 
das nicht erlaubt ist.

Gruesse
Gast #5058378
Lesenswert?

Lars R. schrieb:
> Kaj schrieb:
>> Warum genau ist die xor-Operation auf Pointer nicht zulaessig?
>
> Weil das Unsinn ist (Speicheradressen verwürfeln.)

Nach Sinnhaftigkeit war nicht gefragt!
Wenn es in Assembler (Adressarithmetik,-berechnung) möglich sein, warum 
weigert sich der Compiler? Vorrauseilender Gehorsam im Sinne der MMU?
Gast #5058385
Lesenswert?

Weil die Designer das so entschieden haben. Du wirst feststellen müssen, 
dass praktisch alle binären mathematischen Operationen zwischen 2 
Pointern nicht erlaubt sind - es ist in praktisch jedem Fall ein Fehler 
des Programmierers, der dazu führt. Und wenn es unbedingt trotzdem sein 
muss, kann ein einfacher cast, quasi als "ich weis was ich da mache", 
die Einschränkung aushebeln...
Gast #5058390
Lesenswert?

Guardians of the memory space schrieb:
> Lars R. schrieb:
>> Kaj schrieb:
>>> Warum genau ist die xor-Operation auf Pointer nicht zulaessig?
>>
>> Weil das Unsinn ist (Speicheradressen verwürfeln.)
>
> Nach Sinnhaftigkeit war nicht gefragt!
> Wenn es in Assembler (Adressarithmetik,-berechnung) möglich sein, warum
> weigert sich der Compiler? Vorrauseilender Gehorsam im Sinne der MMU?

Das hat nichts mit Verweigerung zu tun, man hat sich bei der 
Standardisierung von C überlegt welche Operatoren für Adresstypen 
benötigt werden und oh wunder xor ist nicht dabei, weil es keinen 
Anwendungsfall dafür gibt. In C (und überall sonst wo) sind Zeiger eben 
keine Skalare. In Assembler ist das möglich, weil Adressen und alles 
Skalare sind, eine CPU kennt keine Datentypen im klassischen Sinne, 
deshalb ist das in Assembler möglich.
Gast #5058401
Lesenswert?

Kaj schrieb:
> Mich interessiert nur, warum
> das nicht erlaubt ist.

Wenn es technisch sehr einfach möglich wäre zu verhindern, dass ein 
Autofahrer sein Fahrzeug gegen einen Baum lenken kann, fändest du es 
dann sinnvoll oder nicht, dieses Feature in jedes Auto einzubauen?
Gast #5058419
Lesenswert?

Baldrian schrieb:
> So geht es:
Aber nicht auf einem x86_64, denn da sind Pointer größer als Integer. 
Wenn schon mit uintptr_t.

Guardians of the memory space schrieb:
> Wenn es in Assembler (Adressarithmetik,-berechnung) möglich sein
Pointer müssen nicht notwendigerweise Adressen beinhalten, sondern 
können auch mithilfe irgendeiner anderen Form von Referenz implementiert 
sein. Daher macht eine XOR-Operation darauf keinen Sinn. Ohnehin sind 
nur ganz bestimmte wenige Pointerarithmetiken wohldefiniert.

Zum Tauschen zweier Werte gibt es std::swap. Das funktioniert auch mit 
Pointern.
Moderator #5058437
Lesenswert?

Aus

1
#include <algorithm>
2
#include <stdint.h>
3

4
int *x, *y;
5

6
void swap1() {
7
  x = reinterpret_cast<int *>(reinterpret_cast<intptr_t>(x)
8
                            ^ reinterpret_cast<intptr_t>(y));
9
  y = reinterpret_cast<int *>(reinterpret_cast<intptr_t>(x)
10
                            ^ reinterpret_cast<intptr_t>(y));
11
  x = reinterpret_cast<int *>(reinterpret_cast<intptr_t>(x)
12
                            ^ reinterpret_cast<intptr_t>(y));
13
}
14

15
void swap2() {
16
  int *tmp = x;
17
  x = y;
18
  y = tmp;
19
}
20

21
void swap3() {
22
  std::swap(x, y);
23
}

macht der GCC auf meinem PC

1
_Z5swap1v:
2
  movq  y(%rip), %rax
3
  movq  x(%rip), %rdx
4
  movq  %rax, x(%rip)
5
  movq  %rdx, y(%rip)
6
  ret
7

8
_Z5swap2v:
9
  movq  x(%rip), %rax
10
  movq  y(%rip), %rdx
11
  movq  %rax, y(%rip)
12
  movq  %rdx, x(%rip)
13
  ret
14

15
_Z5swap3v:
16
  movq  x(%rip), %rax
17
  movq  y(%rip), %rdx
18
  movq  %rax, y(%rip)
19
  movq  %rdx, x(%rip)
20
  ret

Warum sollte man also nicht das von Johann vorgeschlagene std::swap()
verwenden?
Gast #5058439
Lesenswert?

Dr. Sommer schrieb:
> Baldrian schrieb:
>> Irrelevant. Wichtig ist, dass es auf meinem System funktioniert.

> Genau, wer kommt schon auf die Idee Software zu verkaufen sodass sie
> auch auf dem System des Kunden läuft. Oder sich einen neuen Computer
> zuzulegen.

Danke, dass du mir zustimmst.

Nebenbei: Ich gestatte dir, unter Nennung meines Urheberrechtes und der 
Zahlung von angemessenen Tantiemen, mein Programm in deinem Sinne zu 
erweitern und zu verkaufen. Viel Glück.
Beitrag #5058440 wurde von einem Moderator gelöscht.
Gast #5058464
Lesenswert?

Operatoren sind in C irgendwie definiert.
Sie sind sogar überladen und funktionieren bei unterschiedlichen Typen 
ganz unterschiedlich, auch wenn versucht wird, das ganze in sich stimmig 
zu halten.

int *pi;
int i;

pi++ macht etwas ganz anderes als i++. genauso ist es mit i+3 und 
pi+3. Warum sollte also das mit dem XOR anders sein.
#5058796
Lesenswert?

TriHexagon schrieb:
> Das hat nichts mit Verweigerung zu tun, man hat sich bei der
> Standardisierung von C überlegt welche Operatoren für Adresstypen
> benötigt werden und oh wunder xor ist nicht dabei, weil es keinen
> Anwendungsfall dafür gibt.

Doch, gibt einen.

Du kannst eine doppelt verkettete Liste mit nur einem Pointer pro 
Element basteln, wenn du bei jedem Element "PREV XOR NEXT" speicherst.

Durchlaufen der Liste geht in beide Richtungen, man muss nur immer den 
letzten Pointer aufheben, um den nächsten zu errechnen...
Gast #5058802
Lesenswert?

Εrnst B. schrieb:
> Durchlaufen der Liste geht in beide Richtungen, man muss nur immer den
> letzten Pointer aufheben, um den nächsten zu errechnen..
Na sowas. Das ginge aber auch mit "next - prev". Nur leider darf man 
keine Pointer subtrahieren die nicht in das selbe Array zeigen...
Gast #5059116
Lesenswert?

Ein wesentlicher Grund, wieso Pointer im C-Standard so eingeschränkt 
sind: Das müssen technisch gesehen nicht unbedingt Integer sein. 
Besonders bei Architekturen, die über Segment und Offset arbeiten, oder 
mit Banks.

Das sind dann Implementationsfragen, von denen C gerade abstrahieren 
soll.
#5059900
Lesenswert?

Nop schrieb:
> Ein wesentlicher Grund, wieso Pointer im C-Standard so eingeschränkt
> sind: Das müssen technisch gesehen nicht unbedingt Integer sein.
> Besonders bei Architekturen, die über Segment und Offset arbeiten, oder
> mit Banks.

Bis hin zu Zeigern, bei denen bestimmte Werte komplett ungültig sind und 
nicht mal ohne Hardware-Exception in ein Adress-Register geladen werden 
können. Da könnte dann so ein temporäres XOR-Ergebnis schon das ganze 
Programm zum Absturz bringen.

> Das sind dann Implementationsfragen, von denen C gerade abstrahieren
> soll.

Richtig.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren