Autor Beitrag
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mo 20.08.12 21:44 
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):

ausblenden 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);               // Wert lesen
        v := ChangeEndian32(v);      // Dateiformat nutzt BigEndian, hier passiert ein  bswap EAX
        st.Seek(-4, soFromCurrent);  // zurückspringen

        v := v + diff;               // ändern        
        v := ChangeEndian32(v);
        st.Write(v, 4);              // schreiben
    end;


Dabei kommt natürlich in Zeile 12 eine Warnung bzgl. vorzeichenlose Typen blablub.

Wie macht man sowas richtig? So?

ausblenden 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.

_________________
We are, we were and will not be.


Zuletzt bearbeitet von Gausi am Mo 20.08.12 22:02, insgesamt 1-mal bearbeitet
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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.


Zuletzt bearbeitet von jaenicke am Mo 20.08.12 22:01, insgesamt 1-mal bearbeitet
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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.

_________________
We are, we were and will not be.


Zuletzt bearbeitet von Gausi am Mo 20.08.12 22:03, insgesamt 1-mal bearbeitet
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 20.08.12 22:03 
Ja, hab ich auch gerade realisiert. ;-)
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Mo 20.08.12 22:10 
Mach einfach das, was die Fehlermeldung auch sagt: Beide Operanden wurden erweitert.
ausblenden 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 ;)

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."


Zuletzt bearbeitet von Martok am Mo 20.08.12 22:58, insgesamt 1-mal bearbeitet
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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:

_________________
We are, we were and will not be.