Pointer casten
-
Hallo ihr Experten,
ich hätte da mal ne Frage, ist folgendes erlaubt bzw. definiert ?
unsigned char dummy[4];
dummy[0] = 1;
dummy[1] = 2;unsigned int tmp = (unsigned int) dummy;
dummy[2] und dummy[3] ist undefiniert... wenn ich hier einen int
Pointer nutze ist der Wert abhängig vom Speicherinhalt, das ist klar.
Selbst wenn ich hier nur 2 Bytes lesen werde, ist das überhaupt
erlaubt ?Bin für jede Info dankbar !
-
Jap, ist erlaubt.
Allerdings wäre folgendes sauberer:unsigned int tmp = *reinterpret_cast<unsigned int*>(dummy);
-
Ryuzaki schrieb:
Jap, ist erlaubt.
Allerdings wäre folgendes sauberer:unsigned int tmp = *reinterpret_cast<unsigned int*>(dummy);wieso ?
bringt es vorteile bezüglich der sicherheit bei der programmausführung ?
laufzeitvorteile ?oder findest du
*reinterpret_cast<unsigned int*>(dummy)einfach nur 'optisch sauberer' als
*(unsigned int*) dummy
-
wisondas schrieb:
bringt es vorteile bezüglich der sicherheit bei der programmausführung ?
Grundsätzlich sollte man immer auf die C++ Casts zurückgreifen. Die C-Style Casts sind unsicher.
Weitere Vorteile:
1. Man sieht um was für eine Art der Umwandlung es sich handelt (in diesem Fall wird das Ergebis reinterpretiert). Sprich Lesbarkeit.
2. Man kann besser nach den Stellen im Programmcode suchen.
3. Je nach Art des Casts liefern die C++ Casts eine höhere Sicherheit.cu André
-
hmm evtl. ist union etwas passender für dein Problem als dieses rumgecaste.
-
also grundlegend sollte man es überhaupt nicht ausnutzen dass c++ und c diese ganzen pointer und speicherspiele erlauben und den code sauber halten
selbst mit reinterpret cast würde ich sowas nicht machen, in 99% der fälle ist die performance vernachlässigbar und es gibt sauberere lösungen
natürlich gibt es ausnahmen und vor allem bei fileoperationen ist es so oft bequemer und von da her würde ich sagen ok
also wenn du zb ne binäre datei einliest und das ist ein byte buffer der größe 1000 und du weisst die ersten 40 byte anfangend mit einem offset von 20 sind 10 unsigned integer die irgendwelche werte angeben kannst du ruhig sagen
int offset = 20;
unsigned int *irgendwelcheWerte = (unsigned int *)(buffer + offset);oder ka.. gibt sicher mehrere szenarien wo es ok ist bzw "sicher"
aber das sind ausnahmefälle, und wenn es nicht gerade
- sehr viel overhead verursachen würde es anders zu lösen
- für sehr einfache operationen wie dieses starre file parsen eingesetzt wird
- du wirklich wirklich weisst was du tust und dass es nicht schiefgehen wird und ansonsten ein performance bottleneck darstellen würde es über andere strukturen zu lösen
- ...
würde ich auf solche casts auf jeden fall verzichtenallein schon in deinem fall, wenn das dummy array vom typ short ist und du castest es auf ein integer array, also dein speicher sagen wir sieht so aus
dummy[0] dummy[1] dummy[2] dummy[3] filename length width short short short short rofl\0 int intund jetzt castest du die dummies auf unsigned int und schreibst was drauf, dabei überschreibst du den string (filename) unabsichtlich mit irgendwas und auch das \0 natürlich und der speicher sieht irgendwie so aus
dummy[0] dummy[1] dummy[2] dummy[3] filename length width --- irgend was das du überschreiben hast --- (verfälschter int) intund jetzt willst du filename ausgeben über %s, aber es schließt nicht mehr mit einem \0 ab weil du das überschrieben hast
auf ein mal erstreckt sich dein filename über ka wieviele bytes bis endlich mal sowas wie \0 kommt, vielleicht geht auch alles gut bis irgendwann auf ein mal ein bug auftritt und du wirst jahre brauchen um draufzukommen was überhaupt falsch ist bis du endlich merkst dass du deinen speicher korrupiert hast
-
Vevusio schrieb:
also grundlegend sollte man es überhaupt nicht ausnutzen dass c++ und c diese ganzen pointer und speicherspiele erlauben und den code sauber halten
Wenn du damit auf Casts anspielst: Ja. Man sollte cast vermeiden wenn nicht unbedingt erforderlich (daher lege ich auch darauf Wert das man die casts suchen kann). Aber wenn man Casts benötigt, sollte man auch auf die C++ Casts zurückgreifen.
Wenn du auf Zeiger und Zeigerarithmetik anspielst ist dies nunmal ein Teil von C++ (und C). Ja, man kann es auch übertreiben aber selten lassen sich Zeiger (auch bei einer sauberen Programmierung) gänzlich vermeiden. Zudem ist der Stack auch nicht so groß das du allen Speicher auf diesen packen solltest...
cu André
-
Vevusio schrieb:
also wenn du zb ne binäre datei einliest und das ist ein byte buffer der größe 1000 und du weisst die ersten 40 byte anfangend mit einem offset von 20 sind 10 unsigned integer die irgendwelche werte angeben kannst du ruhig sagen
int offset = 20;
unsigned int *irgendwelcheWerte = (unsigned int *)(buffer + offset);oder ka.. gibt sicher mehrere szenarien wo es ok ist bzw "sicher"
Genau dieses Szenario gehoert leider nicht dazu. Denn solcher Code ist es, der dann auf x86-CPUs laeuft, aber beim Portieren auf PPC nur zu Problemen fuehrt, weil die Byte-Reihenfolge im int andersherum ist.
-
naja fairer weise muss man vermutlich auch sagen dass das wohl nicht das einzige problem sein wird wenn man auf einen pda sein programm übertragen möchte
sondern grundsätzlich das komplette programmdesign (gui, ram auslastung, ..)ich kenne mich zwar nicht aus mit programmierung für pocket pcs aber ich schätze mal dass man programme die sowohl als auch auf einem ppc und einem pc rennen sollen vermutlich entsprechend .NET und dann ohnehin einen bytereader oder sonstige .NET file klassen benutzen werden?
man muss bei sowas halt immer den scope im auge behalten
wenn eine zielsetzung des programms portierbarkeit auf einen pcc ist dann muss man das natürlich beachten
-
er meint nicht Pocket PC sondern http://de.wikipedia.org/wiki/PowerPC