Sto cercando modi per ottenere l'offset di un campo in un record Delphi. Questi 2 metodi seguenti funzionano ma speravo in un modo più pulito. In sostanza avrei voluto che il terzo showmessage funzionasse. Qualche idea?Delphi: Offset del campo record
edit: Bene, la risposta qui sotto funziona bene, grazie! Per avere un riferimento, ecco l'output assembler per le varie opzioni:
---- result:=longint(@abc.c)-longint(abc); ----
lea edx,[eax+$08]
sub edx,eax
mov eax,edx
---- mov eax,offset rec_a.c ----
mov eax,$00000008
---- result:=longint(@rec_a(nil^).c); ----
xor eax,eax
add eax,$08
EDIT2: Sembra che questo è un duplicato di una domanda precedente: previous similar question come indicato di seguito per RRUZ. Come mostrato qui, un altro metodo è dichiarare una variabile globale e usarla come segue. Stranamente il compilatore non è ancora in grado di assegnare il valore corretto al momento della compilazione, come si vede nell'output dell'assembler, quindi per efficienza e leggibilità è meglio usare il metodo nil.
---- var ----
---- rec_a_ofs:rec_a; ----
---- ... ----
---- result:=longint(@rec_a_ofs.c)-longint(@rec_a_ofs); ----
mov eax,$0045f5d8
sub eax,$0045f5d0
edit3: codice revisionato Ok con tutti i metodi per farlo. Si noti che il codice assembler generato per il 3 °, 4 ° e 5 ° metodo (metodo di classe) è identico, sia che siano in linea o meno. Scegli la tua strada preferita quando arrivi a fare questa roba!
type
prec_a=^rec_a;
rec_a=record
a:longint;
b:byte;
c:pointer;
class function offset_c:longint;static;inline;
end;
//const
// rec_a_field_c_offset=longint(@rec_a(nil^).c); // no known way to make this work
{$warnings off}
function get_ofs1:longint;inline;
var
abc:^rec_a;
begin
result:=longint(@abc.c)-longint(abc);
end;
{$warnings on}
function get_ofs2:longint;
asm
mov eax,offset rec_a.c
end;
function get_ofs3:longint;inline;
begin
result:=longint(@rec_a(nil^).c);
end;
function get_ofs4:longint;inline;
begin
result:=longint(@prec_a(nil).c);
end;
class function rec_a.offset_c:longint;
begin
result:=longint(@prec_a(nil).c);
end;
var
rec_a_ofs:rec_a;
function get_ofs6:longint;inline;
begin
result:=longint(@rec_a_ofs.c)-longint(@rec_a_ofs);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(inttostr(get_ofs1));
showmessage(inttostr(get_ofs2));
showmessage(inttostr(get_ofs3));
showmessage(inttostr(get_ofs4));
showmessage(inttostr(rec_a.offset_c));
showmessage(inttostr(get_ofs6));
// showmessage(inttostr(rec_a_field_c_offset));
end;
La parola chiave 'offset' non è necessaria nel codice BASM; solo "mov eax, rec_a.c'. – kludg
possibile duplicato di [Ottieni posizione di una struct var] (http: // stackoverflow.it/questions/13168959/get-position-of-a-struct-var) – RRUZ
@serg codice ridondante può aggiungere sicurezza a Soem - uccidere l'ambiguità dove non te l'aspettavi o fare errori di sintassi dove hai scritto male e codifica più rilassata sarebbe compilabile con risultati errati –