Forum: PC-Programmierung C++: Warum kein xor auf Pointer?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Kaj (Gast)


Bewertung
0 lesenswert
nicht 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

von Lars R. (larsr)


Bewertung
1 lesenswert
nicht lesenswert
Kaj schrieb:
> Warum genau ist die xor-Operation auf Pointer nicht zulaessig?

Weil das Unsinn ist (Speicheradressen verwürfeln.)
1
*x = *x ^ *y;

bzw.
1
*x ^= *y;

von Johann L. (gjlayde) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
1
std::swap (x, y);

o Zeiger sind keine Skalare, sondern eben Zeiger.

o XOR macht Mist wenn die Adressen übereinstimmen.

> Mich interessiert nur, warum das nicht erlaubt ist.

Weil's im C(++) Standard steht.

: Bearbeitet durch User
von Guardians of the memory space (Gast)


Bewertung
-1 lesenswert
nicht 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?

von Tom (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Weil es völlig idiotisch wäre, sowas zu tun.

von Decoder (Gast)


Bewertung
1 lesenswert
nicht 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...

von TriHexagon (Gast)


Bewertung
0 lesenswert
nicht 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.

von Ulli N. (Gast)


Bewertung
-1 lesenswert
nicht 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?

von Baldrian (Gast)


Bewertung
-5 lesenswert
nicht lesenswert
So geht es:
1
    int main()
2
{
3
    int *x;
4
    int *y;
5
    int *z;
6
7
    z = (int)x ^ (int)y;
8
}

von Dr. Sommer (Gast)


Bewertung
1 lesenswert
nicht 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.

von Baldrian (Gast)


Bewertung
-8 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Baldrian schrieb:
>> So geht es:
> Aber nicht auf einem x86_64, denn da sind Pointer größer als Integer.

Irrelevant. Wichtig ist, dass es auf meinem System funktioniert.

von Dr. Sommer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Dumdi D. (dumdidum)


Bewertung
0 lesenswert
nicht lesenswert
Ich vermute das liegt auch daran, das keine 'normale' Arithmetik 
stattfindet. Der numerische Wert von ein Pointer + Zahl ist der 
numerische Wert des Pointers plus die Size des Pointertyps mal Zahl.
D.h. wenn man mit dem Bitmuster arbeiten will kann man ja immer noch 
casten.

von Yalu X. (yalu) (Moderator)


Bewertung
1 lesenswert
nicht 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?

von Baldrian (Gast)


Bewertung
-4 lesenswert
nicht 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 vom Autor gelöscht.
von Nein! (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Baldrian schrieb:
> So geht es:
>     int main()
> {
>     int *x;
>     int *y;
>     int *z;
>
>     z = (int)x ^ (int)y;
> }

Nein!

von Achim.S (Gast)


Bewertung
0 lesenswert
nicht 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.

von Εrnst B. (ernst)


Bewertung
0 lesenswert
nicht 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...

: Bearbeitet durch User
von Dr. Sommer (Gast)


Bewertung
0 lesenswert
nicht 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...

von A. S. (achs)


Bewertung
0 lesenswert
nicht lesenswert
Und zudem muss man dann zu einem Objekt zusätzlich einen weiteren 
Pointer übergeben oder speichern.

: Bearbeitet durch User
von Joachim B. (jar)


Bewertung
0 lesenswert
nicht lesenswert
Ulli N. schrieb:
> 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?

sinnvoller den Baum zu nehmen als am Abhang dem Baum auszuweichen.

: Bearbeitet durch User
von Nop (Gast)


Bewertung
2 lesenswert
nicht 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.

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht 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.

von Nase (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Guardians of the memory space schrieb:
> Wenn es in Assembler (Adressarithmetik,-berechnung) möglich sein, warum
> weigert sich der Compiler? Vorrauseilender Gehorsam im Sinne der MMU?
Nein (bzw. auch, je nach Architektur).
Hauptsächlich wegen Typensicherheit.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.