![]() |
Typisierte vs. Untypisierte Konstante
Hi,
Delphi-Quellcode:
program Project1;
{$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes; const const1 = 'HALLO'#0#0#0; const2: array[0..7] of AnsiChar = 'HALLO'#0#0#0; var foo: array[0..7] of AnsiChar; begin foo := const1; WriteLn(foo = const1); WriteLn(foo = const2); end.
Code:
Warum liefert das erste false?
falter@PC0303:/tmp$ ./project1
FALSE TRUE falter@PC0303:/tmp$ Gruß Felix |
Re: Typisierte vs. Untypisierte Konstante
Der erste Vergleich konvertiert vermutlich beide Operanden nach PChar, sodass ein reiner Zeigervergleich fehlschlägt. Beim zweiten Vergleich hingegen werden zwei statische Arrays verglichen, was durch Vergleich des Speicherinhalts erfolgt. Zeig doch mal den Assemblercode.
|
Re: Typisierte vs. Untypisierte Konstante
Ansonsten, falls das nicht stimmt, hätte ich noch die Theorie, dass der Speicherinhalt verglichen wird und bei der untypisierten Variante noch eine Längenangabe des Strings davor steht. Aber ohne die Opcodes ist das nur Raten.
[Edit]
Code:
Project1.dpr.14: foo := const1;
004040D7 8B057C414000 mov eax,[$0040417c] 004040DD 8905F0874000 mov [$004087f0],eax 004040E3 8B0580414000 mov eax,[$00404180] 004040E9 8905F4874000 mov [$004087f4],eax Project1.dpr.15: WriteLn(foo = const1); 004040EF 8D45EC lea eax,[ebp-$14] 004040F2 BAF0874000 mov edx,$004087f0 004040F7 B908000000 mov ecx,$00000008 004040FC E8CBFAFFFF call @LStrFromArray 00404101 8B45EC mov eax,[ebp-$14] 00404104 BA8C414000 mov edx,$0040418c 00404109 E8D6FAFFFF call @LStrCmp 0040410E 0F94C2 setz dl 00404111 A19C594000 mov eax,[$0040599c] 00404116 E86DF0FFFF call @Write0Bool 0040411B E894F0FFFF call @WriteLn 00404120 E897E9FFFF call @_IOTest Project1.dpr.16: WriteLn(foo = const2); 00404125 B8F0874000 mov eax,$004087f0 0040412A BA94594000 mov edx,$00405994 0040412F B908000000 mov ecx,$00000008 00404134 E81BEEFFFF call @AStrCmp 00404139 0F94C2 setz dl 0040413C A19C594000 mov eax,[$0040599c] 00404141 E842F0FFFF call @Write0Bool 00404146 E869F0FFFF call @WriteLn 0040414B E86CE9FFFF call @_IOTest |
Re: Typisierte vs. Untypisierte Konstante
Hi,
Code:
Hm... Beim ersten mal wird die Variable nach ShortString konvertiert und die nicht typisierte Konstante wohl als ShortString Konstante behandelt, beim zweiten Mal wird beides nach ShortString konvertiert und dann verglichen. Dann muss die Konstante anders aussehen als das umgewandelte Array? Na Schluss für heute,übermorgen werd ich eventuell mal gucken was bei ner Zuweisung an ShortString herauskommt und da sehen wo das Problem liegt.
(gdb) disassemble
Dump of assembler code for function main: 0x08048080 <main+0>: push %ebp 0x08048081 <main+1>: mov %esp,%ebp 0x08048083 <main+3>: sub $0x210,%esp 0x08048089 <main+9>: mov %ebx,-0x210(%ebp) 0x0804808f <main+15>: mov %esi,-0x20c(%ebp) 0x08048095 <main+21>: mov %edi,-0x208(%ebp) 0x0804809b <main+27>: call 0x8058540 <fpc_initializeunits> 0x080480a0 <main+32>: mov 0x8095278,%eax 0x080480a5 <main+37>: mov %eax,0x80b33b0 0x080480aa <main+42>: mov 0x809527c,%eax 0x080480af <main+47>: mov %eax,0x80b33b4 0x080480b4 <main+52>: call 0x805c430 <fpc_get_output> 0x080480b9 <main+57>: mov %eax,%edi 0x080480bb <main+59>: mov $0x8095284,%ebx 0x080480c0 <main+64>: lea -0x100(%ebp),%eax 0x080480c6 <main+70>: push $0x7 0x080480c8 <main+72>: push $0x1 0x080480ca <main+74>: mov $0x80b33b0,%ecx 0x080480cf <main+79>: mov %eax,%esi 0x080480d1 <main+81>: mov $0xff,%edx 0x080480d6 <main+86>: call 0x804a6f0 <fpc_chararray_to_shortstr> 0x080480db <main+91>: lea -0x100(%ebp),%eax ---Type <return> to continue, or q <return> to quit--- 0x080480e1 <main+97>: mov %ebx,%edx 0x080480e3 <main+99>: call 0x804a6b0 <fpc_shortstr_compare_equal> 0x080480e8 <main+104>: test %eax,%eax 0x080480ea <main+106>: sete %cl 0x080480ed <main+109>: mov %edi,%ebx 0x080480ef <main+111>: mov %ebx,%eax 0x080480f1 <main+113>: mov $0x0,%esi 0x080480f6 <main+118>: mov %eax,%edx 0x080480f8 <main+120>: mov %esi,%eax 0x080480fa <main+122>: call 0x805ce40 <fpc_write_text_boolean> 0x080480ff <main+127>: call 0x8058410 <fpc_iocheck> 0x08048104 <main+132>: mov %ebx,%eax 0x08048106 <main+134>: call 0x805c5a0 <fpc_writeln_end> 0x0804810b <main+139>: call 0x8058410 <fpc_iocheck> 0x08048110 <main+144>: call 0x805c430 <fpc_get_output> 0x08048115 <main+149>: mov %eax,%edi 0x08048117 <main+151>: lea -0x100(%ebp),%ebx 0x0804811d <main+157>: push $0x7 0x0804811f <main+159>: push $0x1 0x08048121 <main+161>: mov $0x809528e,%ecx 0x08048126 <main+166>: mov %ebx,%eax 0x08048128 <main+168>: mov $0xff,%edx 0x0804812d <main+173>: call 0x804a6f0 <fpc_chararray_to_shortstr> ---Type <return> to continue, or q <return> to quit--- 0x08048132 <main+178>: lea -0x100(%ebp),%ebx 0x08048138 <main+184>: lea -0x200(%ebp),%eax 0x0804813e <main+190>: push $0x7 0x08048140 <main+192>: push $0x1 0x08048142 <main+194>: mov $0x80b33b0,%ecx 0x08048147 <main+199>: mov %eax,%esi 0x08048149 <main+201>: mov $0xff,%edx 0x0804814e <main+206>: call 0x804a6f0 <fpc_chararray_to_shortstr> 0x08048153 <main+211>: lea -0x200(%ebp),%eax 0x08048159 <main+217>: mov %ebx,%edx 0x0804815b <main+219>: call 0x804a6b0 <fpc_shortstr_compare_equal> 0x08048160 <main+224>: test %eax,%eax 0x08048162 <main+226>: sete %cl 0x08048165 <main+229>: mov %edi,%ebx 0x08048167 <main+231>: mov %ebx,%eax 0x08048169 <main+233>: mov $0x0,%esi 0x0804816e <main+238>: mov %eax,%edx 0x08048170 <main+240>: mov %esi,%eax 0x08048172 <main+242>: call 0x805ce40 <fpc_write_text_boolean> 0x08048177 <main+247>: call 0x8058410 <fpc_iocheck> 0x0804817c <main+252>: mov %ebx,%eax 0x0804817e <main+254>: call 0x805c5a0 <fpc_writeln_end> 0x08048183 <main+259>: call 0x8058410 <fpc_iocheck> ---Type <return> to continue, or q <return> to quit--- 0x08048188 <main+264>: call 0x8058780 <SYSTEM_DO_EXIT> 0x0804818d <main+269>: mov -0x210(%ebp),%ebx 0x08048193 <main+275>: mov -0x20c(%ebp),%esi 0x08048199 <main+281>: mov -0x208(%ebp),%edi 0x0804819f <main+287>: leave 0x080481a0 <main+288>: ret End of assembler dump. @roter Kasten: Das ist von Delphi??? Liefert Delphi denn auch zwei verschiedene Ergebnisse wenn man den Code ausführt? Gruß Felix |
Re: Typisierte vs. Untypisierte Konstante
Ja, obiger Auszug war aus dem Delphi-Debugger, dort ist auch zu sehen, dass 2 verschiedene Vergleichsfunktionen verwendet werden. Das Resultat ist wie von dir beschrieben. Wenn ich das grade richtig interpretiere, werden vorher beim Zuweisen 2 mal je 32 Bit kopiert, also eine identische Kopie als lokale Variable auf dem Stack erstellt.
Die Funktionen erwarten danach verschiedene Parameter bzw. die Parameter auch in anderer Reihenfolge und vor dem ersten Vergleich wird erst noch mal irgendwas aus dem lokalen Array umgewandelt. Ich schau morgen vielleicht noch mal genauer drüber, will jetzt grade Vektorräume und Matrizen für ein Referat morgen nicht auch noch mit Opcodes durcheinander werfen. :stupid: |
Re: Typisierte vs. Untypisierte Konstante
Zitat:
Zitat:
// EDIT: Der rote Kasten macht Urlaub. :mrgreen: |
Re: Typisierte vs. Untypisierte Konstante
das Array of Char wird als PChar mit maximaler Länge angesehn
und
Delphi-Quellcode:
wird als String übersetzt und beim String gehören die #0#0#0 mit zu den gültigen Daten
const1 = 'HALLO'#0#0#0;
[add]
Delphi-Quellcode:
var
s: String; begin foo := const1; s := 'HALLO'#0#0#0; WriteLn(foo = s); s := PChar('HALLO'#0#0#0); WriteLn(foo = s); foo := const2; s := 'HALLO'#0#0#0; WriteLn(foo = s); s := PChar('HALLO'#0#0#0); WriteLn(foo = s); |
Re: Typisierte vs. Untypisierte Konstante
[delete]
|
Re: Typisierte vs. Untypisierte Konstante
Liste der Anhänge anzeigen (Anzahl: 2)
Also: Was passiert ist folgendes:
Zuerst wird LStrFromArray aufgerufen. Was macht das? Es wandelt foo in einen String um. Dessen Länge ist aber 5, da danach nur noch Nullen kommen. So, jetzt wird LStrCmp aufgerufen. Das geht 5 Zeichen durch und merkt, dass die alle identisch sind. Da aber die Länge unterschiedlich war, war der Vergleich dennoch nicht erfolgreich. Die unterschiedlichen Längen und der Zustand nach dem erfolgreichen Vergleich der 5 Zeichen sieht man auf den beiden Screenshots. |
Re: Typisierte vs. Untypisierte Konstante
Hi,
Jetzt weiß ich, wie es bei Delphi wäre. :-) Gut zu wissen, dass es auch bei Delphi nicht identisch ist. Wird das also bei FPC dann in einen ShortString umgewandelt, welcher die Länge 5 statt 8 hat? Denn dem Namen der aufgerufenen Funktion nach wird es in einen ShortString umgeqwandelt. Das wäre allerdings kritisch, da dann beim zweiten Mal, wo ja zwei Umwandlungen in ShortString stattfinden, wo ich die Arrays direkt vergleiche, Die nullen hinten beide Male entfernt werden und dann werden sie nicht mit verglichen. Das heißt ja, wenn am Ende nach der ersten Null etwas anderes kommt dann fällt dies beim Vergleich nicht auf... Muss ich unbedingt morgen ausprobieren wenn ich wieder Zeit dazu habe. Gruß Felix |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz