Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Alternative zu StrpCopy gesucht (https://www.delphipraxis.net/51155-alternative-zu-strpcopy-gesucht.html)

turboPASCAL 7. Aug 2005 07:52


Alternative zu StrpCopy gesucht
 
Moin, ich suche eine Alternative zu StrPCopy. (will keine SysUtils in der uses)

Delphi-Quellcode:
var
  s: String;
  p: PChar;
begin
  s := 'Hallo';

  p := PChar(s);
  p := @S[1];
end.
// -------------------- >
var
  s: String;
  p: array [0..25] of Char;
begin
  s := 'Hallo';
 
  StrPCopy(p, s);

  p := PChar(s); // <-- Inkompatible Typen: 'Array' und 'PChar'
  p := @S[1]; // <--- Inkompatible Typen: 'Array' und 'Pointer'
end.
Ich würde ja die Chars "manuell" in einer For-Schleife umschaufeln, aber gibt es 'ne elegantere Lösung ?

Sprint 7. Aug 2005 19:53

Re: Alternative zu StrpCopy gesucht
 
z.B. die WinAPI Funktionen MSDN-Library durchsuchenlstrcpyn und MSDN-Library durchsuchenlstrcpy.

Luckie 7. Aug 2005 23:15

Re: Alternative zu StrpCopy gesucht
 
Ein PChar ist auch nullterminierend und die Compilermagic nimmt einem da was ab:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  s: String;
  p: PChar;
begin
  s := 'Hello World';
  p := PChar(s);
  ShowMessage(p);
end;
Ansonsten, StrpCopy ruft StrLCopy auf:
Delphi-Quellcode:
function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar; assembler;
asm
        PUSH   EDI
        PUSH   ESI
        PUSH   EBX
        MOV    ESI,EAX
        MOV    EDI,EDX
        MOV    EBX,ECX
        XOR    AL,AL
        TEST   ECX,ECX
        JZ     @@1
        REPNE  SCASB
        JNE    @@1
        INC    ECX
@@1:   SUB    EBX,ECX
        MOV    EDI,ESI
        MOV    ESI,EDX
        MOV    EDX,EDI
        MOV    ECX,EBX
        SHR    ECX,2
        REP    MOVSD
        MOV    ECX,EBX
        AND    ECX,3
        REP    MOVSB
        STOSB
        MOV    EAX,EDX
        POP    EBX
        POP    ESI
        POP    EDI
end;

function StrPCopy(Dest: PChar; const Source: string): PChar;
begin
  Result := StrLCopy(Dest, PChar(Source), Length(Source));
end;
Nachtrag:
Das Rumhantieren mit nullterminuierenden Strings ist meist überflüssig. Oft reicht zum Schluss ein Cast nach PChar, Pointer oder in dem man einen Zeiger auf das erste Zeichen des Strings angibt:

Delphi-Quellcode:
var
  s: String;
begin
  s := 'Hello world';
  Messagebox(hWnd, PChar(s), ...
  Messagebox(hWnd, Pointer(s), ...
  Messagebox(hWnd, @s[1], ...

Muetze1 8. Aug 2005 00:06

Re: Alternative zu StrpCopy gesucht
 
Moin!

Richtig, wenn man einen PChar übergeben will. Was ist aber nun, wenn man einen Buffer übergeben bekommt, den man mit einem PChar füllen soll? Ein typecast ist da dann nicht anwendbar, da er einen eigenen Speicherbereich angibt und nicht den fremdalloziierten, übergebenen Speicher nutzt. Das ist ein grosses Manko was gegen die Compiler Magic bei PChar's spricht. In dem Falle ist man notgedrungen auf StrPCopy() o.ä. angewiesen kann eben mal nicht so einfach ein PChar() TypeCast in den Quelltext schmieren...

MfG
Muetze1

turboPASCAL 8. Aug 2005 14:53

Re: Alternative zu StrpCopy gesucht
 
Thx All, Luckie

x000x 9. Aug 2005 00:15

Re: Alternative zu StrpCopy gesucht
 
Moin moin,

die Frage ist schon beantwortet, aber mal Interesse halber:
Was spricht dagegen, es für das Beispiel von Matti (turboPASCAL) so zu machen?
Delphi-Quellcode:

// ..

procedure TForm1.Button1Click(Sender: TObject);
type
   PArrayOfChar = ^TArrayOfChar;
   TArrayOfChar = array[0..25] of Char;
var
   szStr      : String;
   ArrayOfChar : array[0..25] of Char;
begin
   szStr        := 'Hallo';
   TArrayOfChar(ArrayOfChar) := PArrayOfChar(Pointer(szStr))^;
   ShowMessage(ArrayOfChar);
end;

Olli 9. Aug 2005 00:46

Re: Alternative zu StrpCopy gesucht
 
Vielleicht sollten wir an dieser Stelle nochmal auf Motzis Stringtut verweisen?

Olli 9. Aug 2005 21:59

Re: Alternative zu StrpCopy gesucht
 
Um die Frage von Peter noch schnell zu beantworten, habe ich seinen Code mal in leicht abgeänderter Form:
Code:
begin
   [color=green]szStr        := 'Hallo';[/color]
   [color=red]TArrayOfChar(ArrayOfChar) := PArrayOfChar(Pointer(szStr))^;[/color]
   [color=blue]MessageBox(0, ArrayOfChar, ArrayOfChar, 0);[/color]
end.
...ausgetestet und disassembliert und danach kommentiert. Sollte also auch für Assemblerunkundige verständlich sein.
Code:
[color=gray]CODE:004038D4 start:
CODE:004038D4                 push   ebp
CODE:004038D5                 mov    ebp, esp
CODE:004038D7                 add    esp, 0FFFFFFF4h
CODE:004038DA                push   esi
CODE:004038DB                push   edi
CODE:004038DC                mov    eax, offset dword_4038AC
CODE:004038E1                 call   @Sysinit@@InitExe$qqrv ; Sysinit::__linkproc__ InitExe(void)
CODE:004038E6                 xor    eax, eax
CODE:004038E8                 push   ebp
CODE:004038E9                 push   offset ExceptionHandler
CODE:004038EE                push   dword ptr fs:[eax]
CODE:004038F1                 mov    fs:[eax], esp[/color]
; ------------------------------------------------------------------------
[color=#80FF80][b]; Hier wird in den Registern (Aufrufkonv. "register") der literale und der
; Zielstring übergeben![/b][/color]
[color=green]CODE:004038F4                 mov    eax, offset szStr ; Destination
CODE:004038F9                 mov    edx, offset aHallo ; Source (literal string)
CODE:004038FE                call   @System@@LStrAsg$qqrv ; System::__linkproc__ LStrAsg(void)[/color]
; ------------------------------------------------------------------------
[color=#FF8080][b]; Diese 2 Zeilen könnte man in eine stecken, aber das soll mal egal sein,
; wichtig ist, daß hier der Pointer auf den Puffer des Strings in
; ESI (Quellpointer-Register) geladen wird[/b][/color]
[color=red]CODE:00403903                 mov    eax, ds:szStr
CODE:00403908                 mov    esi, eax       ; Init ESI[/color]
[color=#FF8080][b]; Hier wird das Offset auf den Puffer - ArrayOfChar - in EDI (Zielpointer-Register)
; geladen.[/b][/color]
[color=red]CODE:0040390A                mov    edi, offset ArrayOfChar ; Init EDI[/color]
[color=#FF8080][b]; Anzahl der auszuführenden Wiederholungen[/b][/color]
[color=red]CODE:0040390F                mov    ecx, 6[/color]
[color=#FF8080][b]; Wiederhole ECX-mal das Kopieren von jeweils einem DWORD von ESI
; nach EDI[/b][/color]
[color=red]CODE:00403914                 rep movsd              ; Copy 6 DWORDs from
CODE:00403914                                         ; ESI to EDI[/color]
[color=#FF8080][b]; Kopiere 2 weitere Bytes ...[/b][/color]
[color=red]CODE:00403916                 movsw                  ; Copy 2 more bytes[/color]
; ------------------------------------------------------------------------
[color=#8080FF][b]; "Umgekehrte" Übergabe der Parameter auf den Stack und Aufruf von MessageBox()[/b][/color]
[color=blue]CODE:00403918                 push   0
CODE:0040391A                push   offset ArrayOfChar
CODE:0040391F                push   offset ArrayOfChar
CODE:00403924                 push   0
CODE:00403926                 call   MessageBoxA_0[/color]
[color=gray]CODE:0040392B                xor    eax, eax
CODE:0040392D                pop    edx
CODE:0040392E                pop    ecx
CODE:0040392F                pop    ecx
CODE:00403930                 mov    fs:[eax], edx
CODE:00403933                 push   offset loc_403940
CODE:00403938
CODE:00403938 locret_403938:                         ; CODE XREF: CODE:0040393Ej
CODE:00403938                 retn[/color]
Ich habe den Code ausführlichst kommentiert. Einfach mal reinschauen.

Fazit: Es spricht nichts dagegen. Offenbar ermöglicht der Compiler eine Zuweisung eines Zeichenarrays an ein anderes Zeichenarray indem dies transparent in einen Kopiervorgang (zudem einen effektiven - weil ohne zusätzlichen Aufruf) übersetzt wird.

Es spricht also nichts dagegen :zwinker:


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:34 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz