Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

birdfreeyahoo

Alter Hase

  • »birdfreeyahoo« ist der Autor dieses Themas

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

1

27.09.2015, 01:35

[C++] typlose Pointerarithmetik/Adressverschiebung

Hi, ich habe ein kleines Problem/Frage.

Ich will alle IP's in einem Netz mit der Subnetzmaske 255.255.255.0 herausfinden.
Dafür habe ich diesen Code in einer for-Schleife stehen.
Er kopiert meine IP und soll einen Pointer auf den letzten Byte holen (lastByte), damit ich den Gerätecode hochlaufen lasse.
Jetzt hat ein Freund gemeint, dass durch die Addition von 3, der Pointer um 12 Byte verschoben wird, weil der Typ int ist.
Aber ich denke, mit dem &-Operator habe ich ja eine Adresse und wenn ich diese um 3 erhöhe, dann müsste sie doch um 3 Byte höher sein.
Oder stimmt das wirklich, dass der Typ in dem Ausdruck &newIP noch vorhanden ist und ich damit einen kompletten int überspringe pro Inkrementierung?

Also ich frage mich warum das passiert, weil eigentlich dachte ich dass eine Adresse typlos ist, nicht umsonst kann ich zwischen Pointern hin und her casten (und kann damit auch Daten verlieren, wenn ich die Größe nicht mehr weiß).

C-/C++-Quelltext

1
2
        unsigned int newIP = m_pCore->m_LocalIP;
        unsigned char* lastByte = (unsigned char*)(&newIP + 3);

2

27.09.2015, 01:55

warum so kompliziert?
Mach doch einfach lastByte = IP & 255
Damit bekommst du das letzte Byte und musst nicht mit komischen Pointern rumhacken.

birdfreeyahoo

Alter Hase

  • »birdfreeyahoo« ist der Autor dieses Themas

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

3

27.09.2015, 02:18

Aber ich will ja einen Pointer auf den Byte haben, weil ich ihn direkt verändern will. Außerdem interessiert mich das einfach egal ob ich es jetzt verwende ;)

Tobiking

1x Rätselkönig

  • Private Nachricht senden

4

27.09.2015, 04:45

Zeiger werden immer um die länge des Zeigertyps verschoben. Dein Freund hat schon recht das dein Code bei der Klammerung die Adresse um 3 * sizeof(unsigned int) erhöht.

Ich vergleiche das immer gerne mit Arrays:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;

int main() {
    int a[5] = {1, 2, 3, 4, 5 };
    int n = 3;
    int* p = a;
    
    cout << a[n] << " = " << *(p+n) << " = " << *(n+p) << " = " << n[a] << endl; // Ausgabe 4 = 4 = 4 = 4
    return 0;
}


Also ich frage mich warum das passiert, weil eigentlich dachte ich dass eine Adresse typlos ist, nicht umsonst kann ich zwischen Pointern hin und her casten (und kann damit auch Daten verlieren, wenn ich die Größe nicht mehr weiß).

Eine Adresse hat zwar keinen Typ, ein Zeiger auf eine Adresse, wie es der Adressoperator zurückliefert, aber schon ;)

Das Argument mit dem Cast macht irgendwie keinen Sinn. Man kann jeden Typen in jeden anderen Typen casten wenn man es explizit angibt. Vor allem mit dem C style cast passiert das. Das Ergebnis davon kann aber undefiniert sein und damit im besten Fall zu einem offensichtlichen Fehler oder Crash führen. Wenn man rohe Daten hin und her interpretiert sollte man schon wissen was man tut. Vielleicht verwechselst du das auch mit C, wo es implizite Casts zwischen Zeiger gibt. Da ist die Typsicherheit nicht so stark und man kann sich noch einfacher in den Fuß schießen.

birdfreeyahoo

Alter Hase

  • »birdfreeyahoo« ist der Autor dieses Themas

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

5

27.09.2015, 06:08

Ok ich habe es jetzt verstanden ich ging davon aus, dass der Adressoperator sozusagen eine typlose Adresse liefert, die bei der Zuweisung zu einem Pointer implizit sozusagen umgewandelt wird.
Aber es ist ja logisch, wenn ich ein dynamisches Array per Pointer habe und in einer for-Schleife iteriere, springe ich auch per Inkrementierung zum nächsten Element, also mehr als 1 Byte.
Da ich gerade rohe Pakete (also alles selber, Ethernet-Header etc.) für Netzwerke zusammenbaue, hab ich viel mit Pointer-Casts und Adressverschiebungen zu tun.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

27.09.2015, 10:26

Ich glaube nicht, dass Du da viel mit Adressverschiebungen zu tun hast oder haben solltest, denn das geht alles prima mit den Operaten | und &, sowie << und >>. Das ist bei Fehlern wesentlich sicherer.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

7

27.09.2015, 11:25

Ich rate auch zu dem Bitoperatoren.
Pointerarithmetik hat hier den Nachteil, dass es vom Endian abhängt.
Bei jedem anderen Typ als char verletzt man außerdem die Strict Aliasing Rule.

birdfreeyahoo

Alter Hase

  • »birdfreeyahoo« ist der Autor dieses Themas

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

8

27.09.2015, 16:15

Ok jetzt habe ich zum Beispiel ein Paket als unsigned char Array.
Wie kann ich miz Bitoperatoren zu den verschiedenen Headern springen?
Bisher habe ich es so gemacht:

C-/C++-Quelltext

1
2
3
ETH_HDR* eth = (ETH_HDR*)aPacket;
IP_HDR* ip = (IP_HDR*)(aPacket + sizeof(ETH_HDR));
ICMP_HDR* icmp = (ICMP_HDR*)(aPacket + sizeof(ETH_HDR) + sizeof(IP_HDR));

9

27.09.2015, 16:25

Wieso denn springen?
Du hast dir das paket doch sicherlich zusammen gebaut. Dann wirst du ihn einfach in umgekehrter Reihenfolge abbauen müssen.
Für serialisierung in C++ werden üblicherweise auch die stream operatoren (<< >>) benutzt. Wenn du statt eines plain arrays auf ein std::array zurückgreifst, hast du das alles schon in fertiger Art und Weise vorliegen.

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

10

27.09.2015, 16:39

Ne, die Stream-Operatoren funktionieren so in C++ leider nicht. Die funktionieren nur mit Textdaten und auch das eher schlecht als recht. Selbst wenn man mit Text arbeiten wollen würde, müsste man sie für die Strukturen noch implementieren.
In wie fern hier ein std::array hilft ist mir auch nicht klar.

Falls du binäre Daten einliest, ist das tatsächlich der einfachste Weg. C++ hat hier leider wenig Konfortfunktionen.

Werbeanzeige