Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - CopyMemory -> Move


jeng - Fr 16.10.15 11:49
Titel: CopyMemory -> Move
Hallo,

Kann mir vieleicht hier jemand weiterhelfen.

Ich müsste das

Delphi-Quelltext
1:
2:
3:
4:
5:
Var s: String;
begin
s:= Edit1.Text;
CopyMemory(@MyRec[x].ExoName[0].b, PChar(s), Length(s) *SizeOf(Char)); 
...


in sowas

Delphi-Quelltext
1:
 Move(Pchar(s[1]), MyRec[x].ExoName[0].b[0], length(s) * sizeof(char));                    
umwandeln.


Danke für Hilfe.


Martok - Fr 16.10.15 12:08

Und was ist jetzt die Frage? Der PChar-Cast in der Move-Version ist überflüssig, ansonsten ist das syntaktisch schon richtig (wobei man über sizeof(char) und die unterschiedlichen Kodierungen noch diskutieren könnte).

Warum eigentlich?


jeng - Fr 16.10.15 12:20

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Warum eigentlich?


Die copymemory variante ist ohne #0, und das bekomme ich nicht in der move variante hin.

Edit: Eine Null Terminierung hinter jedem Zeichen muss ich weg bekommen, und copymemory geht nicht in FMX.

Moderiert von user profile iconNarses: Beitragsformatierung überarbeitet.


Martok - Sa 17.10.15 23:17

Achso, stimmt ja. CopyMemory ist ja aus der WinAPI.

user profile iconjeng hat folgendes geschrieben Zum zitierten Posting springen:
Edit: Eine Null Terminierung hinter jedem Zeichen muss ich weg bekommen, und copymemory geht nicht in FMX.
Ah, dann hast du ein Delphi mit Strings als Widestrings, richtig?

Da wäre der String dann also vorher in AnsiString umzukopieren. Dann entfällt auch das *sizeof(char) wieder, weil das dann fest 1 wird.


Holgerx - So 18.10.15 09:02

Hallo..

Da ich den DatenTyp für MyRec[x].ExoName[0].b nicht kenne, hier ein Beispiel mit Strings:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure MoveStringData(ASource : stringvar ATarget : string);
var
  iLength : integer;
begin
  iLength := length(ASource);
  setLength(ATarget,iLength { * SizeOf(Char)});  // Speicher erstellen, da ATarget der gleiche String-Typ wie Source ist, entfällt das SiseOf
  move(ASource[1],ATarget[1],iLength * SizeOf(Char));
end;


Bei Move wird 'ein' Speicherbereich von Source nach target kopiert, dazu muss das Ziel bereits groß (Speicher) genug sein, um die Bytes aus der Quelle aufnehmen zu können!

Dem Move ist es egal ob Ansistring oder Widestring, es kopiert einfach nur zusammenhängende 'Bytes'.

Durch das 'SizeOf(Char)' wird bei AnsiStrings ein Byte pro Zeichen, bei UniCode zwei Bytes pro Zeichen kopiert, somit funktioniert die obrige Funktion unter allen Delphi-Versionen , welche move und string kennen!

Somit muss vor dem kopieren nach 'MyRec[x].ExoName[0].b' dieses b groß genug sein, um den String 's' aufnehmen zu können.

---------

Edit:
OK, es geht nur darum aus einem WideString (2 Bytes je Char) ein AnsiString (ein Byte je Char) zu machen, dann genügt wirklich:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure MoveStringData(ASource : AnsiString; var ATarget : AnsiString);
var
  iLength : integer;
begin
  iLength := length(ASource);
  setLength(ATarget,iLength { * SizeOf(Char)});  // Speicher erstellen, da ATarget der gleiche String-Typ wie Source ist, entfällt das SizeOf
  move(ASource[1],ATarget[1],iLength {* SizeOf(Char)});
end;

var
  tmpStr : AnsiString;
  
begin
  tmpStr := Edit1.Text;
MoveStringData(tmpStr,tagertStr)