* * * *

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 23, 2024, 02:59:50 am

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

108 Visitatori, 0 Utenti

Autore Topic: Quest - Se lo sai rispondi  (Letto 1143 volte)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1396
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Quest - Se lo sai rispondi
« il: Dicembre 16, 2021, 07:20:40 pm »
Codice: [Seleziona]
type
  TPolloNoM = record
    d1: integer;
  end;

type
  TPolloM = record              //Managed record
    pollo: array of integer;
    e1: integer;
  end;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    function Prova(a: integer; var B: integer; const c: TForm; const d: TPolloNoM; const e: TPolloM): boolean;
  public
    { Public declarations }
    c1: integer;
  end;

var
  Form1: TForm1;
  PolloNoM: TPolloNoM;
  PolloM: TPolloM;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var a1, b1: integer;
begin
  a1 := 5;
  b1 := 5;
  Form1.c1 := 5;
  PolloNoM.d1 := 5;
  PolloM.e1 := 5;
  Prova(a1, b1, Form1, PolloNoM, PolloM);
  //Dopo la chiamata di cui sopra, che valori hanno a1, b1, Form1.c1, PolloNoM.d1, PolloM.e1 (da notare che alcuni sono passati come CONST)
end;

function TForm1.Prova(a: integer; var B: integer; const c: TForm; const d: TPolloNoM; const e: TPolloM): boolean;
var cp, dp, ep: pointer;
begin
  a := 20;
  b := 20;
  cp := @(c as TForm1).c1;
  move(b, cp^, sizeof(b));
  dp := @d.d1;
  move(b, dp^, sizeof(b));
  ep := @e.e1;
  move(b, ep^, sizeof(b));
  Result := True;
end;

Senza eseguire il programma, sapete dire:

che valori hanno a1, b1, Form1.c1, PolloNoM.d1, PolloM.e1 dopo la chiamata a "Prova" (da notare che alcuni sono passati come CONST nella funzione) ?
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2921
  • Karma: +20/-4
Re:Quest - Se lo sai rispondi
« Risposta #1 il: Dicembre 17, 2021, 09:14:34 am »
DragoRosso, ti sembrano domande da fare alle 19:20 di sera?  ;D ;D ;D
Imagination is more important than knowledge (A.Einstein)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1396
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Quest - Se lo sai rispondi
« Risposta #2 il: Dicembre 17, 2021, 09:19:20 am »
Bhè, invece di mezzanotte .... pensavo fosse un orario migliore  ;D ;D ;D

Uhmm .... dici che ho scombussolato la digestione dei lettori a quell'ora ?  :P :P

Chissà  se avrò qualche risposta istintiva dagli utenti.

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

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1396
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Quest - Se lo sai rispondi
« Risposta #3 il: Dicembre 18, 2021, 02:54:58 pm »
Sciolgo il dilemma sulla "quest".

Ricordo che la funzione interessata ha la seguente definizione:

Codice: [Seleziona]
function Prova(a: integer; var B: integer; const c: TForm; const d: TPolloNoM; const e: TPolloM): boolean;

Ad una prima sommaria vista, mi aspetterei che i parametri nella funzione definiti come CONST siano appunto non modificabili all'interno della procedura, e quindi che il solo parametro "B" sia interessato dalla modifica avendo quindi il seguente risultato:

Codice: [Seleziona]
  a1 rimane 5;
  b1 diventa 20;
  Form1.c1 dovrebbe rimanere 5;
  PolloNoM.d1 dovrebbe rimanere 5;
  PolloM.e1 dovrebbe rimanere 5;

Invece non è proprio così. O almeno non lo è con i normali settaggio del compilatore.

Per capire ciò, dobbiamo prima analizzare le regole riguardante il passaggio dei parametri.
Facendo un breve sunto, i parametri possono essere passati per valore o riferimento.

Senza alcun specificatore le variabili integrali (ad esempio quelle definite INTEGER, BOOLEAN, DOUBLE) sono passate per valore, cioè nello stack (o nei registri della CPU ove sia abilitato ciò) viene posto copia del valore della variabile. La procedura quindi leggerà il valore, ma l'eventuale modifica dello stesso verrà persa all'uscita della procedura stessa senza modifica del valore originale (quello del chiamante).

Quando invece come parametro passiamo una qualsiasi variabile "strutturata" (dagli array ai record, dalle classi alle interfacce) nello stack viene passato il riferimento alla variabile (quindi il puntatore alla stessa). Stessa cosa avviene quando immettiamo nella definizione della procedura il modificatore "VAR" (in questo caso viene passato il riferimento qualunque sia il tipo di variabile passato).

Quando viene passato un riferimento, TUTTE le modifiche effettuate nella procedura nelle variabili indicate come parametri si riflettono anche nelle originali.
Occorre quindi stare all'occhio e fare attenzione a come le procedure sono definite per capire cosa si fà, al fine di evitare alcune problematiche poi difficili da identificare.

Tra le varie opzioni, si può inserire la definizione di "CONST" nei parametri per istruire il compilatore a "rifiutare" e segnalare la modifica alla variabile "parametro".
Questa opzione però funziona solo per le assegnazioni esplicite (vedi l'esempio di seguito), ma NON per le assegnazioni derivate. Nel codice oggetto di questo TOPIC, io ho usato questo metodo (assegnazione derivata) aggirando il compilatore e rendondo NULLO ciò che il progettista voleva indicare: la CONST dei parametri.

DI NUOVO, fate attenzione a come usate i puntatori, perchè possono provocare danni collaterali difficili da prevedere e valutare. A mio parere, e mi sono già espresso abbondantemente su questo argomento, il ricorso all'uso dei puntattori e peggio ancora alla sua matematica dovrebbe essere limitata ai soli casi indispensabili.

Analizziamo quindi cosa accade e come i risultati siano estremamente diversi da quello che ci si aspetterebbe:

Codice: [Seleziona]
  a1 rimane 5;   // OK
  b1 diventa 20;            //OK
  Form1.c1 diventa 20;    //sarebbe dovuto rimanere 5;
  PolloNoM.d1 diventa 20;    //sarebbe dovuto rimanere 5;
  PolloM.e1 diventa 20;    //sarebbe dovuto rimanere 5;

 a1: nella procedura l'assegnazione di a := 20 viene persa.
 b1: nella procedura l'assegnazione di b := 20 viene applicata correttamente (parametro VAR)
 Form1.c1, PolloNoM.d1, PolloM.e1: nella procedura questi valori vengono passati come riferimento (regola per il passaggio dei parametri)
 e quindi la modifica di C, D, E anche se definiti CONST si riflette all'origine. L'uso dei puntatori aggira il compilatore VIOLANDO LA REGOLA CONST.
 Se avessi tentato la modifica diretta nella procedura (esempio c.c1 := 20;), il compilatore avrebbe emesso un errore tipo" la parte sinistra non può essere assegnata".

Il tutto come curiosità.

EDIT: il comportamento indicato è specifico per Lazarus, in altri mondi il risultato è ancora più diverso (e per certi versi più complesso da analizzare). Ad esempio in Delphi PolloNoM.d1 sarebbe rimasto 5 .....  :o

Ciao ciao.
 
« Ultima modifica: Dicembre 19, 2021, 11:36:01 am da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

doc

  • Jr. Member
  • **
  • Post: 96
  • Karma: +2/-0
  • "L'Ingegnere sa quello che fa e fa quello che sa".
    • Spagnotto Ing. Mirko
Re:Quest - Se lo sai rispondi
« Risposta #4 il: Dicembre 20, 2021, 10:50:12 am »
@DragoRosso

Sei un mago, spiegazione senza pecche. 10+

 

Recenti

How To

Utenti
  • Utenti in totale: 803
  • Latest: maXim.FI
Stats
  • Post in totale: 19170
  • Topic in totale: 2287
  • Online Today: 100
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 108
Total: 108

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.