* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Novembre 10, 2024, 07:18:50 pm

Inserisci il nome utente, la password e la durata della sessione.

101 Visitatori, 1 Utente
 

Autore Topic: Il peso dei record  (Letto 2255 volte)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1379
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Il peso dei record
« Risposta #15 il: Luglio 27, 2023, 04:45:38 pm »
Non c'è problema sulla discussione, approfondire và comunque bene.

Riguardo al valore, non contarci molto sul fatto che rimanga a zero quando non è valida. Il dato dipende dalla stringa e anche se una buona parte darà zero come data (che secondo me comprende la rappresentazione di un NAN per le date), ci saranno anche i casi in cui la data non sarà zero.

Per quello che riguarda la condivisione e quindi la rappresentazione come variante in realtà è utile in diversi casi (sempre meno, però ...), come ad esempio:

Codice: [Seleziona]
Esempio per condividere aree di memoria: in questo caso condivide un valore single (32 bit) con la sua rappresentazioe a byte.

type
  TConverterRec = record
    case Boolean of
      false: (ByteArray: array[0..3] of Byte);
      true: (FloatValue: Single);
  end;

var
  Pippo: TConverterRec;

procedure TForm1.Button1Click(Sender: TObject);
var s: single;
begin
  s:= 0.43; //$3EDC28F6  Valore 0,43 in single float
  Pippo.ByteArray[0] := $F6;
  Pippo.ByteArray[1] := $28;
  Pippo.ByteArray[2] := $DC;
  Pippo.ByteArray[3] := $3E;
  ShowMessage(floattostr(Pippo.FloatValue));
end;

Ovviamente sono situazioni che è possibile usare, come il GOTO (  :-X ) ma che volendo si possono anche porre in oblio.

Ciao

P.S.: ho citato l'utilità, ad esempio quando si ha a che fare con vecchi PLC dove non è possibile leggere un valore float se non a byte, e con questo trucco è comoda e abbastanza sicura la "conversione".
« Ultima modifica: Luglio 27, 2023, 04:49:08 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1379
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Il peso dei record
« Risposta #16 il: Luglio 27, 2023, 05:10:25 pm »
Tuttavia, anche se ho compreso le spiegazioni fornite, trovo il fatto di allocare lo stesso la memoria per le variabili comprese in una variant-part un po' fuorviante.
Se non fossero allocate sarebbe più logico e semplice poter effettuare un controllo in fase di parsing del codice, evitando errori.
Inoltre, se il padding è il vero problema, non comprendo perché non poter utilizzare anche nelle variant-part dei puntatori "mascherati" (ad es. string al posto di string[xxx]).

Se un campo rappresenta una variabile "complessa", come un oggetto o una stringa o ..., allora il campo diventa un puntatore. Il tutto viene mascherato dal compilatore e quindi il programmatore non deve preoccuparsi. L'unico eventuale problema, che però è abbastanza diffuso, sarebbe quello di fare eventualmente la copia "in un colpo solo" del record ... cosa che non si può fare se il record ha appunto dei campi con variabili non integrali.
Lavorare quindi con i puntatori (simil "C") è abbastanza rischioso perchè:
Codice: [Seleziona]
var
  p: string[3];
e
Codice: [Seleziona]
var
  p: string;
hanno internamente due rappresentazioni diverse (questo in generale, poi si possono forzare alcuni comportamenti con l'uso delle opzioni di compilazione).

Inoltre provate a pensare un domani se cambi qualcosa nelle dichiarazioni e devi andare a rivederti tutti gli usi fatti con quella variabile ... un suicidio.

Meglio usare le "cose" ben definite e intrinseche nel linguaggio, in modo da evitare il più possibile bagni di sangue.

Faccio ancora un esempio banale:
Codice: [Seleziona]
var
   p: array [0..4] of integer;
   i: integer;

//NON FATELO COSI !!!!!!!!!!!!!!!!!!!!!!!!!
for i := 0 to 4 do
  p[i] := i; //è solo un esempio di assegnazione
//Se per qualche motivo devo variare la lunghezza dell'array diventerò scemo a correggere i for, i while e chissà cos'altro.

//FATE COSI'
for i:= Low(p) to High(p) do
  p[i] := i; //è solo un esempio di assegnazione
//Questo funzionerà sempre senza alcuna correzione

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2917
  • Karma: +20/-4
Re:Il peso dei record
« Risposta #17 il: Luglio 27, 2023, 05:54:06 pm »
rimetto il link di qualche risposta fa
https://wiki.freepascal.org/Record#Variable_structure

ci trovate questo esempio che segue dove, con lo stratagemma della memoria condivisa, si può vedere una variabile come word, byte alto e byte basso o, udite udite, come sequenza di bit

direi che è una funzionalità veramente unica :)

Codice: [Seleziona]
type
  TSpecialWord = record
    case Byte of
      0: (Word_value: Word);                      // 7
      1: (Byte_low, Byte_high: Byte);             // 7, 0
      2: (Bits: bitpacked array [0..15] of 0..1); // 1, 1, 1, 0, 0, ...
  end;
Imagination is more important than knowledge (A.Einstein)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1379
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Il peso dei record
« Risposta #18 il: Luglio 27, 2023, 07:03:13 pm »
@nomorelogic anche esempio postato in testa a questa seconda pagina del topic (condivisione single con byte  :D ).

Questo è un esempio di codice, create una app e inserite un TButton, fate doppio click (per generare l'evento onclick) e sovrascrivete tutto il codice con questo.

E' solo un esempio.

Codice: [Seleziona]
unit Unit1;

{$IFDEF FPC}
  {$mode Delphi}{$H+}
  {$modeswitch advancedrecords}
{$ENDIF}

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, DateUtils, StdCtrls, TypInfo, Rtti;

type TEnumTipoDato = (Nullo=0, StatoNasc, DataNasc);

type TAnagrafica = record
  Nome: string;
  Cognome: string;
  function InserisciDato(Value: string): WordBool; overload;
  function InserisciDato(Value: TDateTime): WordBool; overload;
  function LeggiDato(var DatoLetto: variant): TEnumTipoDato;
  //INTERNALLY USED, DON'T CALL EXPLICYTY
  {$IFDEF FPC}
    class operator Initialize (var Dest: TAnagrafica);
  {$ELSE}
    class operator Initialize (out Dest: TAnagrafica);
  {$ENDIF}
  //INTERNALLY USED, DON'T CALL EXPLICYTY
  class operator Finalize (var Dest: TAnagrafica);
  strict private
    TipoDato: TEnumTipoDato;
    Dato: string;
end;


type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Anagrafica: TAnagrafica;

implementation

{$R *.lfm}

{$IFDEF FPC}
  class operator TAnagrafica.Initialize (var Dest: TAnagrafica);
{$ELSE}
   class operator TAnagrafica.Initialize (out Dest: TAnagrafica);
{$ENDIF}
begin
  dest.Nome := '';
  dest.Cognome := '';
  dest.TipoDato := Nullo;
  dest.Dato := '';
end;

class operator TAnagrafica.Finalize (var Dest: TAnagrafica);
begin
  ;
end;

function TAnagrafica.InserisciDato(Value: string): WordBool;
begin
  Dato := Value;
  TipoDato := StatoNasc;
  Result := true;
end;

function TAnagrafica.InserisciDato(Value: TDateTime): WordBool;
begin
  Dato := DateTimetoStr(Value);
  TipoDato := DataNasc;
  Result := true;
end;

function TAnagrafica.LeggiDato(var DatoLetto: variant): TEnumTipoDato;
begin
  Result := TipoDato;
  case TipoDato of
    Nullo:
      begin
        DatoLetto := '';
      end;
    StatoNasc:
      begin
        DatoLetto := Dato;
      end;
    DataNasc:
      begin
        DatoLetto := StrToDateTime(Dato);
      end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  tempdato: variant;
  p: TEnumTipoDato;
begin
  //
  Anagrafica.InserisciDato(now);
  //Leggi il dato: .. il dato è in vari formati, dipende da come è stato inserito
  p := Anagrafica.LeggiDato(tempdato);
  ShowMessage(VarToStr(tempdato));
  //
  Anagrafica.InserisciDato('Ahhh ... Parigi');
  //Leggi il dato: .. il dato è in vari formati, dipende da come è stato inserito
  p := Anagrafica.LeggiDato(tempdato);
  ShowMessage(VarToStr(tempdato));
end;

end.

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2917
  • Karma: +20/-4
Re:Il peso dei record
« Risposta #19 il: Luglio 27, 2023, 07:16:01 pm »
sono anziano, le cose a volte mi sfuggono  ;D
Imagination is more important than knowledge (A.Einstein)

 

Recenti

How To

Utenti
  • Utenti in totale: 802
  • Latest: Il Faro
Stats
  • Post in totale: 19115
  • Topic in totale: 2281
  • Online Today: 114
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 1
Guests: 101
Total: 102

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.