Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Cardinal bzw. DWord und Integer mischen
Gausi - Mo 20.08.12 21:44
Titel: Cardinal bzw. DWord und Integer mischen
Ich hab da mal wieder eine Frage, an der man merkt, dass ich so'n Kram nicht gelernt hab. :mrgreen:
Ich habe einen TStream, in dem ich eine Reihe von DWords um einen bestimmten Wert ändern muss (vergrößern oder verkleinern). Das probier ich erstmal so (Effizienz bzgl. der Streamoperationen mal auslassen. Das geht vermutlich schneller, wenn ich erst alles in ein Array of DWord einlese, verändere, und dann zurückschreibe):
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure fFixAudioOffsets(st: TStream; diff: Integer); var v: Dword; begin for i := 1 to Anzahl do begin st.Read(v, 4); v := ChangeEndian32(v); st.Seek(-4, soFromCurrent); v := v + diff; v := ChangeEndian32(v); st.Write(v, 4); end; |
Dabei kommt natürlich in Zeile 12 eine Warnung bzgl. vorzeichenlose Typen blablub.
Wie macht man sowas richtig? So?
Delphi-Quelltext
1: 2: 3: 4: 5:
| if diff >= 0 then v := v + DWord(diff) else v := v - DWord(abs(diff)); end; |
Edit: Titel ergänzt.
jaenicke - Mo 20.08.12 21:54
// EDIT:
Sorry, ist schon spät. :oops: Hab mich vertan.
Casten kannst du einen Cardinal ruhig in einen DWord, wenn du 100% sicher bist, dass der Wert darin nicht zu groß wird. (Denn sonst hättest du ja aufgrund der internen Darstellung plötzlich negative Zahlen.)
Ich würde da aber lieber ULONG bzw. LongWord nehmen, da Cardinal ein Metatyp ist, DWord aber nicht.
Gausi - Mo 20.08.12 22:01
Sind DWord und Cardinal nicht beides 32bit-Vorzeichenlose-Ganzzahltypen, also praktisch identisch? Das dachte ich zumindest immer. :gruebel:
[Edit] Es geht also um das Mischen von DWord mit Integer. ;-) [/Edit]
Und ja, die Werte sind immer so, dass man der Rechnung im gültigen Bereich liegt.
jaenicke - Mo 20.08.12 22:03
Ja, hab ich auch gerade realisiert. ;-)
Martok - Mo 20.08.12 22:10
Mach einfach das, was die Fehlermeldung auch sagt: Beide Operanden wurden erweitert.
Delphi-Quelltext
1:
| Cardinal(Int64(v) + diff) |
Ein "shut up and
mov eax, diff; add v, eax" gibts leider nur in FPC; was gehen könnte (nicht getestet):
inc(v, diff). Keine Ahnung, ob das geprüft wird...
Edit (da hier anscheinend alle hinterher editieren :mrgreen:): du kannst auch den Integer blind auf DWORD casten. Das gibt dann einen übergelaufenen dword, wenn der zum anderen addiert wird kommt dann der Grund ins Spiel warum 2's Complement für negative Werte verwendet wird und alles stimmt wieder ;)
Gausi - Mo 20.08.12 22:11
Ok, also geht das nur vernünftig über die Fallunterscheidung? Denn das erscheint mir etwas merkwürdig. :nixweiss:
Edit, ah, ok. Also erst das DWord auf Int64 bringen (Integer reicht ggf ja nicht), und dann hinterher wieder "kürzen"? Das mit inc probier ich auch mal, das sieht für mich ganz gut aus. :D
Einen (positiven) Integer in ein DWord casten sollte ja immer reibungslos gehen, und ebenso den Betrag eines negativen. Auf einen Bereichsüberlauf bei der Addition/Subtraktion lass ich es einfach drauf ankommen. Dann ist das neu getaggte 4GB-File halt kaputt. :mrgreen:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!