2016-06-10 4 views
1

Ich schreibe einen Logger in C++, und ich bin zu dem Teil gekommen, wo ich einen Protokolleintrag machen und in eine Datei schreiben möchte.Was bedeutet reinterpret_cast binär?

Ich habe eine LogRecord Struktur erstellt und möchte sie serialisieren und in eine Datei im Binärmodus schreiben.

Ich habe einige Beiträge über die Serialisierung in C++, lesen und eine der Antworten enthalten diese folgenden Ausschnitt:

reinterpret_cast<char*>(&logRec) 

Ich habe versucht, das Lesen über reinterpret_cast und was es tut, aber ich konnte nicht ganz verstehen Was passiert wirklich im Hintergrund?

Von was ich verstehe, nimmt es einen Zeiger auf meine Struktur, und verwandelt es in einen Zeiger auf ein Zeichen, so dass es denkt, dass der Teil des Speichers, der meine Struktur enthält, tatsächlich eine Zeichenfolge ist, ist das wahr? Wie kann das funktionieren?

+1

"Im Gegensatz zu static_cast, aber wie const_cast, kompiliert der Ausdruck reininterpret_cast nicht zu irgendwelchen CPU-Anweisungen. Es ist eine reine Compiler-Direktive, die den Compiler anweist, die Bitfolge (Objektdarstellung) von Ausdruck so zu behandeln, als ob sie den Typ hätte neuer Typ." source: http://en.cppreference.com/w/cpp/language/reinterpret_cast Was als nächstes passiert, hängt von deinem Code ab - behandle 'reininterpret_cast' als eine große Vorsichtsmarkierung bei der Code-Überprüfung. –

+2

Nicht "ist eigentlich eine Zeichenkette", sondern "ist eigentlich ein Zeiger auf" char "". Strings ist nur eine der Anwendungen von 'char *'. – molbdnilo

+0

Mögliches Duplikat von [reinterpret \ _cast] (http://stackoverflow.com/questions/4748232/reininterpret-cast) – Leon

Antwort

9

Eine Speicheradresse ist nur eine Speicheradresse. Speicher ist nicht von Natur aus etwas Besonderes - es ist nur eine riesige Menge von Bytes, für alle, die uns interessieren. Was dem Gedächtnis seine Bedeutung gibt, ist das, was wir damit machen, und die Linsen, durch die wir es sehen.

Ein Zeiger auf eine Struktur ist nur eine ganze Zahl, die einen gewissen Offset in den Speicher angibt - sicherlich können Sie eine ganze Zahl auf beliebige Weise behandeln, in Ihrem Fall als Zeiger auf eine beliebige Anzahl von Bytes (char s).

reinterpret_cast() macht nichts besonderes, außer dass Sie eine Ansicht einer Speicheradresse in eine andere Ansicht einer Speicheradresse konvertieren können. Es liegt immer noch an Ihnen, diese Speicheradresse korrekt zu behandeln.

Zum Beispiel ist char* die konventionelle Art, auf eine Zeichenfolge in C++ zu verweisen - aber der Typ char* bedeutet wörtlich "ein Zeiger auf ein einzelnes Zeichen". Wie wird daraus ein Zeiger auf eine nullterminierte Zeichenkette verstanden? Per Konvention, so ist es. Wir behandeln den Typ je nach Kontext unterschiedlich, aber es liegt an uns, dies richtig zu machen.

Zum Beispiel, woher wissen Sie, wie viele Bytes durch Ihre char* Zeiger auf Ihre Struktur gelesen werden? Der Typ selbst gibt Ihnen keine Informationen - es liegt an Ihnen zu wissen, dass Sie wirklich einen byte-orientierten Zeiger auf eine Struktur fester Länge haben.

Denken Sie daran, unter der Haube hat die Maschine keine Typen. Ein Stück Papier ist es egal, ob du in jeder Zeile einen Aufsatz schreibst oder ob du das ganze Ding kritzelst. So behandeln wir es - und wie behandeln die Werkzeuge (C++) es?

+1

Wow, @antiduh, danke!Ihre Antwort hat mir wirklich geholfen, zu verstehen, was ich durch das Kodieren mache. Es scheint so logisch und wahrscheinlich für die meisten gegeben, aber ich habe es bisher nicht so gedacht! – Asaf

3

Binär, tut es überhaupt nichts. Dieses Gießen ist ein übergeordnetes Konzept, das in keiner tatsächlichen Maschinenanweisung enthalten ist.

Auf einer niedrigen Ebene ist ein Zeiger nur ein numerischer Wert, der eine Speicheradresse enthält. Es gibt nichts zu tun, um den Compiler zu informieren "obwohl Sie dachten, dass der Zielspeicher einen struct enthielt, denken Sie jetzt bitte, dass er einen char enthält". Die tatsächliche Adresse selbst ändert sich in keiner Weise.

0

Die Umwandlung einer Struktur in ein Array von Bytes (Zeichen) ist eine klassische Methode mit geringer Auswirkung auf die binäre Serialisierung. Dies basiert auf der Annahme, dass der Inhalt der Struktur zusammenhängend im Speicher existiert. Das Casting ermöglicht es uns, diese Daten unter Verwendung der normalen APIs in eine Datei oder einen Socket zu schreiben.

Dies funktioniert jedoch nur, wenn die Daten zusammenhängend sind.Dies gilt für C-Stil-Strukturen oder PODs in C++ - Terminologie. Es wird nicht mit komplexen C++ - Objekten oder irgendeiner Struktur mit Zeigern auf Speicher außerhalb der Struktur arbeiten. Für Textdaten müssen Sie Zeichenfelder fester Größe verwenden.

struct { 
    int num; 
    char name[50]; 
}; 

wird korrekt serialisieren.

struct { 
    int num; 
    char* name; 
}; 

wird nicht korrekt serialisiert, da die Daten für die Zeichenfolge außerhalb der Struktur gespeichert werden;

Wenn Sie senden die Daten über ein nework Sie auch sicherstellen müssen, dass die Struktur verpackt ist oder zumindest bekannte Ausrichtung und dass ganze Zahlen in einen konsistenten Endian umgewandelt werden (Netzwerk-Byte-Reihenfolge ist in der Regel Big-Endian)

1

Von was ich verstehe, nimmt es einen Zeiger auf meine Struktur, und verwandelt es in einen Zeiger auf ein Zeichen, so dass es denkt, dass der Teil des Speichers, der meine Struktur enthält, tatsächlich eine Zeichenfolge ist, ist das wahr?

Ja.

Wie kann das funktionieren?

Ein String ist nur eine Folge von Bytes, und Ihr Objekt ist nur eine Sequenz von Bytes, so wie es funktioniert.

Aber es wird nicht, wenn Ihr Objekt ist logisch mehr als nur eine Folge von Bytes. Jede Umleitung, und Sie werden abgespritzt. Darüber hinaus ist jede implementationsdefinierte Auffüllung oder Darstellung/Endianität und Ihre Daten nicht portierbar. Dies könnte akzeptabel sein; Es hängt wirklich von Ihren Anforderungen ab.