Newsgroup: it.comp.lang.delphi
Titolo: Comportamento strano dei cicli FOR.. DO

Non frequento molto il newsgroup ma ho un problema urgente che non
riesco a risolvere.
Scrivo una funzione semplice per inizializzare a zero una matrice
bidimensionale a partire da un certo valore (8)
for i:=1 to 10 do
  for j:=8 to 10 do
    mat[i][j]:='0'
con i e j due var integer;
Mi accade questo che andando a monitorare le var I e J in debug, alla
prima chiamata i parte 11 e scende,  mentre j parte da 10 e si ferma
ad 8.
Accade anche con while e repeat.
Premetto che non ci sono variabili globali con  le stesso nome.
Posso cambiare qualsiasi nome alle variabili ma il risultato è lo
stesso.
Prima dei cicli le variabili (mai utilizzate prima) hanno una valore?!
diverso da zero.
Se cancello tutto il mio programma (tutte le funzioni ben 13 pagine di
codice) i cicli funzionano come dovrebbero.
Le uniche variabile globali sono:
Una matrice bidimensionali di stringhe
2 variabile intere
una variabile stringa
AIUTO!!!!
Gianni

 ad 8.
Ma alla fine la matrice č inizializzata bene??
In un thread precedente si era appurato che nel caso non venga usato le
variabili indice (forse in questo caso Delphi l'ha ritenuto comunque
ottimizzabile "capendo" cosa stavi facendo una inizializzazione e che un
verso o l'altro era indifferente) all'interno del ciclo, il compilatore
autonomamente ottimizzava il codice facendolo partire dal massimo e
procedere verso il minimo in quanto a livello di microprocessore, registri o
altre cosette del genere, fare un -1 č leggermente piů veloce di fare +1.
Ciao
Matteo

Ti riporto il breve listato:
 begin
      for x:=0 to 15 do
        for y:=1 to 8 do
          with mat[x][y] do
            begin
              valore:='';
            end;
  end;
alla prima chiamata:
x=16 (?!)
y=8
alla seconda chiamata:
x=16
y=7
....
x=16
y:=1
...
x:=15
y:=8
Quando
x=1
y=1
il blocco termina.
Io dico se mat= array [0..15]*[1..15]
Cosa dovrei fare io? 
with mat[x-1][y]   ?!
Scusate ma devo capire.
Perchè poi dovrebbe intepretare e non eseguire?

 Perchè poi dovrebbe intepretare e non eseguire?
Mi devo essere spiegato io.
Che il sistema faccia:
      for x:=0 to 15 do
        for y:=1 to 8 do
          with mat[x][y] do
            begin
              valore:='';
            end;
Oppure internamente
      for x:=15 to 0 downto
        for y:=8 to 1 downto
          with mat[x][y] do
            begin
              valore:='';
            end;
A te cosa cambia??? dopo questo blocco la matrice è inizializzata male? io
non credo. E quindi, se il compilatore ti ottimizza (= +veloce) il codice
facendolo andare indietro anzichè avanti e, al fine del funzionamento del
programma, è indifferente, perchè preoccuparsi? ;)
Il sorgente ovviamente rimane uguale, ma in fase di compilazione Delphi
esegue una serie di ottimizzazioni per migliorare le prestazioni
dell'eseguibile.
Ad esempio:
A:=5
A:=5+1;
Che senso ha generare codice per la prima istruzione? tanto il suo valore
viene ignorato da quella successiva! quindi Delphi furbescamente ignora la
prima istruzione...
Prova a disattivare l'ottimizzazione nelle proprietà del programma e a fare
il rebuild. Testa se fa ancora uguale...
ciao
Matteo


Hai perfettamente ragione.
Il tuo esempio calza.
Ma se fosse stato:
Mat è il solito array [0.15][1..15] bidimensionale.
for x:=0 to 15 do
  for y:= 1 to 15 do
   (stampa il valore di mat[x][y])
Voglio stampare i valori scandendo la matrice.
Alla prima chiamata
x=16
y=8
Non mi da errore ma mi tira fuori caratteri sballati perchè avevo
dichiarato mat[0..15] ?!
mentre il valore mat[0][1..8] non viene preso in considerazione.
Comunque ho provato anche ad eliminare l'ottimizzazione senza ottenere
risultato.
Gianni

 y=8
Intendi dire (stampa il valore di x e di y)?
Allora, intendi dire che hai un codice in una unit che fa qc. del genere:
type
   ary : array [1..15] of integer;
var
   mat = array [0..15] of ary;
procedure xxyyzz;
var x, y: integer;
begin
   for x:= Low(mat) to High(mat) do
     for y := Low(ary) to High(ary) do begin
       Memo1.Lines.Add ( 'x = '+IntToStr(x)+' y = '+IntToStr(y));
       mat[x][y] := 0;
     end;
end;
A proposito, il brakpoint per vedere i valori dove lo metti? Mi son 
perso qualcosa, ma mi pare che se non lo metti sulla riga 
dell'assegnazione, x ed y possono valere qualsiasi cosa perchè ancora 
Delphi non esegue gli statement realmente, ma solo nel momento 
dell'assegnazione del valore della matrice devono avere il valore richiesto.
Hai attivato il Range Check nelle opzioni di compilazione e rifatto il 
buildd di tutto? (lo chiedo perchè non ho capito se lo hai fatto o no, 
nel caso che sia a posto, ignora il suggerimento).
Ciao.
Mimmo.

dichiarato mat[0..15] ?!
Assolutamente no.
L'ottimizzazione del compilatore non va contro la logica di
funzionamento del programma.  Quando inizializzi una matrice
la logica di funzionamento e' : "inizializzare una matrice"
e sia che lo si faccia in un verso, che in quello opposto il
risultato non cambia.  Nel caso della stampa degli elementi,
invece, la logica e' "stampa in sequenza elemento per
elemento" e il compilatore si adegua.  Quando esso sa che
invertire l'ordine di incremento di un contatore di ciclo
non influisce sulla logica di funzionamento del programma,
allora e' libero di compiere tutte le ottimizzazioni che
vuole.  Nel caso dei decrementi al posto degli incrementi,
la cosa si spiega col fatto che, incrementando, a livello di
codice assembly, c'e' bisogno di testare la condizione di
uscita dal ciclo con due istruzioni (cmp e jz), mentre,
sfruttando i registri flag del processore, con il decremento
e' possibile usarne solo una (jz).  C'e' un mio post, a
riguardo, di qualche tempo fa.
-- 
Andrea Laforgia (
walkie...@libero.it
)
"Usenet is a strange place" [Dennis Ritchie]

Ringrazio tutti per l'interesse e per l'aiuto.
E' vero la funzione viene svolta lo stesso (delphi ha ottimizzato
decrementando le var i ed j invece di incrementarle)
Quello che chiedo io è in caso di errore, come faccio a scoprirlo con
debug step by step se le variabili da me controllate (watch) a causa
dell'ottimizzazione di delphi non eseguono quello da me richiesto?
C'è un altro metodo?
Ricordo che la funzione era:
var
i,j : integer;
mat: array [0..15] of array [1..15] of string;
begin
  for i:=0 to 15 do
    for j:=8 to 15 do
       mat[i][j]:=''
end;
Alla prima chiamata con debug i=16 mentre j = 8
Se stai cercando un errore pensi di averlo trovato quando vedi
mat[i][j] diventa mat[16][8] alla prima chiamata.
Come posso fare un debug senza avere l'ottimizzazione del dephi?
Ho provato a spuntare dall'opzioni di progetto la casella
ottimizzazioni senza ottenere risultato.
Ringrazio.
Gianni

dell'ottimizzazione di delphi non eseguono quello da me richiesto?
Se vuoi evitare l'ottimizzazione: o informi il compilatore
che la variabile ti serve nell'ordine corretto (per esempio,
dichiarando una variabile intera a, che incrementi con il
valore di i e j ad ogni ciclo, in modo che il compilatore
debba necessariamente seguire l'ordine corretto) oppure,
piu' semplicemente, disabiliti l'ottimizzazione da
Project/Options/Compiler, togliendo la spunta a
"Optimization".


"Gigi" ha scritto nel messaggio
|
| Come posso fare un debug senza avere l'ottimizzazione del dephi?
|
| Ho provato a spuntare dall'opzioni di progetto la casella
| ottimizzazioni senza ottenere risultato.
|
Usa la direttiva di compilazione {$O}:
{$o-}
procedure Qualcosa;
var
i,j : integer;
mat: array [0..15] of array [1..15] of string;
begin
  for i:=0 to 15 do
    for j:=8 to 15 do
       mat[i][j]:=''
end;
{$o+}
I e J ora seguono l'incremento che ti aspetti.
--
Ciao.
ACSH
[D4]
---------------------------
Chi fa da se'
fatica il doppio

 
Prego.
Ciao.
Mimmo.

Grazie a tutti.
Ora ho capito il comportamento di delphi.
Comunque viene fatto anche despuntando l'ottimizzazione.
Salutoni e grazie ancora.

Comunque viene fatto anche despuntando l'ottimizzazione.
Sulla mia macchina "despuntando" l'ottimizzazione, viene
abolito quel meccanismo...


abolito quel meccanismo...
Forse dipenderà dalla quantità di codice scritto.
Ad esempio con la direttiva [O-] ho risolto molti cicli for, ma ad
altri sono rimasto con il medesimo problema.
Ciao