Newsgroup: it.comp.lang.c
Titolo: definizione di variabili

Una domanda sulla definizione di variabili :
Lo standard specifica qualcosa in merito a questo punto ?
cioè potrei usare il "paradigma" tipico del c++ che dice di
"definire le varibili nel punto in cui si intende utilizzarle" oppure 
sono obbligato a
metterle in testa ad ogni blocco o inizio funzione ?
so che il compilatore me lo fa fare (l'approccio del c++), ma lo std che 
dice ?
voi come vi comportate in merito ?
meny thanks.

On Jul 19, 12:29 pm, softwareEngineer <ov77NOS...@NOSPAMlibero.it>
wrote:

in c89, la definizione deve essere all'inizio del blocco.
Ciao!
P.S. Personalmente definisco in questo modo le variabili su qualsiasi
linguaggio di programmazione, visto che praticamente è IMO il metodo
più "pulito" per scrivere e leggere il codice...

 piů "pulito" per scrivere e leggere il codice...
pascal docet.
Anche se in C99 č lecito avere un declaration come prima clausola di un
for quindi volendo una cosa di questo tipo:
for (int i = 0; i < 10; i++)
č standard C99.

Sinceramente, IMHO, preferisco l'approccio C++ ... definire
la variabile nel momento in cui la si usa per focalizzare la lettura
(o scrittura) sull'algoritmo ...
Voi che std utilizzate ? C89 ?


 più "pulito" per scrivere e leggere il codice...
In molti linguaggi di programmazione questo stile sarebbe completamente
innaturale e ti costringerebbe a codice boilerplate assurdo. Altri
linguaggi addirittura te lo impediscono proprio sintatticamente. Quindi
il fatto di farlo in "qualsiasi linguaggio di programmazione" mi sembra
un po' fortina. ;)
In generale, tendo molto a diffidare di discorsi del tipo "faccio cosi'
nel mio linguaggio preferito e faccio cosi' ovunque". Generalmente si
finisce per sbagliare da qualche parte. O avere in mente uno scope molto
piu' limitato di quello che si e' detto.
Riguardo alla pulizia, sono convinto che sia essenzialmente una
questione di abitudine, ma sia soprattutto subordinato ad altre
questioni stilistiche. Io sono un fan delle funzioni *molto* brevi. In
questo caso e' possibile fare quello che dici tu.
Viceversa se uno (imho sbagliando) previlegia funzioni lunghe, avere le
dichiarazioni in testa tende a confondere il codice. Ovviamente farebbe
bene ad accorciare le funzioni, ma tant'e'.
Personalmente non mi dispiace per variabili poco importanti limitare lo
scope usando un blocco apposta. Ma come tutte le cose stilistiche,
dipende molto caso per caso IMHO. Le regole generali hanno solo una
validita' generale, per l'appunto.
-- 
-riko

softwareEngineer ha scritto:

Come già ti hanno suggerito, solo nello standard C99
è possibile "definire le varibili nel punto in cui si intende
utilizzarle".
Personalmente sono portato a definire variabili in questo modo
quando si tratta di contatori nei cicli 'for'. Questo per esempio
ti permette di fare economia di variabili e snellire un po' il codice.
Immagina che in una funzione devi usare 5 cicli 'for' (non annidati,
in questo caso), allora, invece di dichiarare 5 contatori:
	int i, j, k, m, n;
preferisco scrivere 5 volte for(int i = 0; ...; ...); certo, potresti
comunque usare la sola 'i' ricordandoti di assegnarle 0 prima di ogni
ciclo, ma anche in questo caso definirla all'interno di 'for' lo trovo
personalmente il modo migliore. Ovviamente ricorda che se scrivi:
	for(int i = 0; ...; ...){
		[...]
	}
non potrai usare direttamente il valore di 'i' fuori da questo ciclo,
cosa che magari vorresti nel caso il ciclo si interrompe e vuoi sapere
in corrispondenza di quale valore di 'i' è successo (in questo caso,
all'interno del ciclo 'for' dovresti assegnare la 'i' ad una variabile
visibile al di fuori del 'for').
Problema che non sussiste nel caso:
	int i;
	for(i = 0; ...; ...){
		[...]
	}
Fuori dal 'for', la 'i' ha l'ultimo valore che aveva nel ciclo.
Quindi il punto di definizione della variabile dipende anche dall'uso
e dalla visibilità che vuoi attribuirle.
Chiaramente finchè si tratta di interi, non ci sono troppi problemi
nella definizione di variabili al consueto 'inizio' di una funzione.
Tuttavia, se dovrai definire un oggetto di dimensioni di un certo
rilievo, è pur sempre preferibile farlo nel momento in cui davvero
devi utilizzarlo, perchè una volta definito, l'oggetto occupa memoria.
-- 
Vincenzo Mercuri

 e dalla visibilità che vuoi attribuirle.
qui ho usato il termine 'definizione' come equivalente a 
'dichiarazione'; tuttavia i due concetti sono ben distinti.
La sola 'int i;' è di fatto una dichiarazione.
-- 
Vincenzo Mercuri


Per essere una regola deve esserci un'eccezione :-)
Ciao!


In C non hai mai questo problema con le definizioni - allochi comunque
(tipicamente sullo stack, quindi praticamente senza overhead)


 troppo lunga (oppure, se li ha innestati, hai sbagliato algoritmo).
Si, quoto!
-- 
-riko

 Per essere una regola deve esserci un'eccezione :-)
Ovviamente!
-- 
-riko


D'accordo, ma a questo punto si ritorna da capo: se lo devi creare a
metà di una funzione perché sei un'altro "blocco logico" dovresti fare
un'altra funzione. Oppure se lo devi creare solo all'interno di un if
o for hai lo stesso effetto del C (ovvero scope e creazione al
blocco).
<snip>
Ciao!

 all'inizio del blocco.
Si ma che motivo c'è di allocare una consistente quantità di
memoria troppo presto? Non sono d'accordo, meglio limitare l'uso
di un'oggetto a quando serve realmente. L'oggetto non esisterà più
all'uscita dal blocco dov'è stato definito. Ed è quello che un
programmatore di solito vorrebbe.
-- 
Vincenzo Mercuri


int pippo(int c)
{
    int a;
    a = 27;
    /* ... */
    if (c==3) {
        struct la_mia_struct test;
        /* ... */
        a = test.membro;
    }
    return a;
}
se questo è il caso a cui ti riferivi allora:
- test esiste solo nel blocco dello if, e dura quanto ti serve
- la funzione è (per me) sbagliata: se fosse nella mia base code la
correggerei, servono due funzioni.
Ovviamente sempre premettendo - in C e non in altri linguaggi.
Ciao!

 correggerei, servono due funzioni.
Ovviamente questo è un esempio che mi trova d'accordo
con te. Non è assolutamente utile limitare la visibilità
di quella struttura al solo blocco 'if'. E' una questione
di utilità. Può capitare per esempio di leggere una matrice
e assegnarla temporaneamente a un'altra, al tempo
stesso modificare l'originale con un thread, e copiare
parti della matrice temporanea nella matrice originaria.
Lì per esempio, personalmente non terrei la matrice temporanea
in memoria per tutto l'algoritmo implementato in quella funzione.
Vale naturalmente che, fare così, non è una regola.
Come avevo sottolineato in precedenza è importante
stabilire la visibilità che necessita una variabile
e poi dichiararla dove risulta più opportuno.
-- 
Vincenzo Mercuri

 e poi dichiararla dove risulta più opportuno.
A me piace dichiarare quando serve in generale, anche perché è più
probabile che mentre usi la variabile il tipo ti rimanga sott'occhio.
Certo in C ci sono dei compilatori che ci avvertono di possibili errori,
ma se si evita di farli è meglio ancora.
In particolare odio dover fare ogni volta (infatti uso stc=c99)
--8<---------------cut here---------------start------------->8---
int i;
...
for (i = 0; .)
--8<---------------cut here---------------end--------------->8---
Però domanda stupida, perché preoccuparsi tanto di cosa viene tenuto in
memoria?
Non è forse possibile che compilando con flags di ottimizzazione ci
pensi il compilatore a generare codice furbo che non si mette ad
allocare memoria inutilmente?
Se fatto solo per scopi di risparmio di memoria mi sembra un po'
un'ottimizzazione prematura...

Andrea Crotti ha scritto:

La mia filosofia (e di tanti altri...) è che la migliore
ottimizzazione si fa scrivendo del buon codice. Va bene
affidarsi ad un buon compilatore, ma è ancora meglio
aver cura da sè di ogni minimo aspetto del proprio programma.
Io preferisco fare così, naturalmente rispetto l'opinione
di altre persone, che magari programmano in C da più tempo di me.
-- 
Vincenzo Mercuri

 un'ottimizzazione prematura...
Quoto in pieno. Il codice è per le persone, non per le macchine.
Oltretutto i compilatori sono fatti apposta per ottimizzare meglio il
codice più "comune", quindi discostarsi con pseudo-micro-
ottimizzazioni non aiuta per nulla. Senza contare che solo il
compilatore di ogni architettura sa cosa effettivamente è
un'ottimizzazione per la macchina target: chi scrive codice con la
pretesa che sia portabile si deve fidare ;-)
Ciao!

FtM ha scritto:

:-) ragazzi (chi lo è un po' meno mi lasci passare il vocativo
affettuoso), la vostra fiducia nei confronti del compilatore
sembra più una fede, che io condivido fino a un certo punto..
Le performance di un programma anche dopo l'ottimizzazione
del compilatore si possono misurare. E spesso si possono
migliorare solo mettendo le mani sul codice.
Mi trovate d'accordo riguardo comuni ottimizzazioni che si sà
già dall'inizio il compilatore farà. Ci sono tools e
contro-tools che misurano queste caratteristiche e le sorprese
anche dopo aver compilato con i 'bambini' di
Stallman, Navia, Microsoft, Intel (ecc...) sono tante.
Se già non le conoscete, vi consiglio di leggere queste guide
molto preziose che riguardano il C++ per certi aspetti, ma
anche il C per molti altri:
http://www.agner.org/optimize/
Spero le troverete interessanti. Non servono
tanto ad avvalorare le mie opinioni, che appunto
rimangono mie, ma sono letture che possono affinare
le conoscenze, soprattutto di chi ama la programmazione
a basso e 'medio' livello.
-- 
Vincenzo Mercuri


Gli darò un'occhiata sicuramente. Il C++ però è un altro mondo. In C è
difficile avere overheads "nascosti" all'interno di un buon codice
(cosa che invece accade quasi sempre in C++, dove spesso devi
scegliere un compromesso tra leggibilità ed ottimizzazione).
In C le ottimizzazioni le puoi fare a livello di algoritmo (che spesso
dipende anche dalla macchina su cui girerà per questioni di caching,
numero di registri, parallelizzazione, etc.etc.) o a livello di micro-
ottimizzazioni (secondo me inutili perché ci pensa il compilatore).
Mentre ha senso perdere tempo sul primo punto, il secondo è, IMO,
quasi inutile.
Detto questo, per completezza non si può non ricordare che
l'ottimizzazione in senso "puro" è spesso improduttiva se il tempo che
serve per ottimizzare il codice non è equilibrata da un evidente
guadagno "complessivo". Un programmatore costa più di una macchina (e
anch'io preferisco staccare un'ora prima e andare a prendermi una
birra se il corrispettivo è far correre una macchina per venti secondi
in meno su un'operazione che dura un'ora).
Su questo so che qualcuno questionerà, ma questa è solo questione di
buon senso :-D
Ciao!


Bah, a me sembri una persona molto presuntuosa e che crede
di avere sempre più esperienza di altri.
Io ho tanti dubbi sempre e comunque, perchè ritengo di dover
sempre imparare. Tu ne hai pure, ma il tuo orgoglio
è così forte che non ammetterai mai di essere solo un parolaio.
Ciao, e divertiti nel tuo piccolo mondo senza overhead (a parole).
Sputare sentenze prima di affrontare i fatti è tipico dell'ignoranza.
Divertiti col 'tuo' linguaggio C.
(ps: la tua esperienza ha prodotto solo una libreria abbastanza 
ridicola, posso dirtelo anch'io che non programmo da molto tempo)
-- 
Vincenzo Mercuri


wrote:

In parte hai ragione, nel fatto che sono presuntuoso e che penso
spesso di essere meglio degli altri, ma questo non ha niente a che
vedere col mio lavoro ;-)
Sulla mia esperienza sul linguaggio basta leggere quello che posto
qui, non mi sembra di aver mai dato consigli sbagliati. Ogni cosa che
scrivo la avvallo con spiegazioni ed esempi, magari rispondendo poco
educatamente forse, ma più di quanto non abbia fatto te (per esempio
in questo thread te con l'OP).
Per la libreria si tratta, come ho spiegato e come evidentemente non
hai letto, di codice parte di altri progetti open-source che sto piano
piano riunendo in un altro progetto open-source. Infatti non ho
espresso alcun tipo di vanto (ci mancherebbe!) ma ho richiesto
consigli e opinioni (mi pare fosse addirittura questo il titolo del
thread). Non mi pagano certo per scrivere quella e ho poco tempo da
dedicarci.
Fortunatamente, indipendentemente da quello che pensi lavorativamente
di me, ho il supporto del fatto che da quando lavoro la programmazione
mi ha sempre dato il pane :-D
Ciao!

 Ciao!
Ciao a te
-- 
Vincenzo Mercuri


La mia identità ed il mio lavoro non sono certo segreti. Se cerchi su
internet trovi quel che faccio, il mio curriculum, i miei progetti
aperti, etc.etc. Se non t'interessa è più che comprensibile, e se mi
giudichi da quel che vedi qui va benissimo lo stesso. Nella vita sono
come scrivo ( solo un po' più brutto :-D ).
A questo punto ti potrei dire "dimmi dove ho sbagliato" o "fammi
vedere il *tuo* codice", ma sarei solo polemico e probabilmente io ho
sbagliato molte volte e forse programmi meglio di me: per quel che mi
riguarda io ho la mia idea e te la tua, fine della storia.
Prima di chiudere il discorso ampiamente OT, se te la sei presa perché
ho scritto:
"Giustissimo, prova a misurare :-) Io a suo tempo l'ho fatto."
anche qui non volevo essere sarcastico (prova effettivamente a
misurare se hai ragione!), e sul fatto che io l'abbia fatto (se non ci
credi) sicuramente troverai sempre su internet più di un contest di
benchmarks nel quale ho partecipato con risultati di timing (fatti per
vari scopi, tra cui il principale era il divertimento) - forse trovi
anche qualche post messo qui di uno specifico tra C e C++ - sempre
riguardo al famoso "overhead" per cui mi prendi in giro :-D
Ciao!

 Prima di chiudere il discorso ampiamente OT, se te la sei presa perché [...]
Ho voluto rispondere a quella che mi era sembrata 'troppa ostinazione'.
Leggo con interesse quel che scrivi, solo che a volte non mi
piacciono certi caratteri... Ma se sei così probabilmente ci farò
l'abitudine :-) 'Prendermela'...a me alla fine fa più piacere avere
delle discussioni in questo contesto che non in altri.
Nel rispetto delle tue idee, ti mando una stretta di mano.
-- 
Vincenzo Mercuri


Ricambio :-)

 blocco).
Sullo "spezzare le funzioni", in principio sono sempre d'accordo. In
pratica non sempre e' cosi' ovvio e/o comodo e/o desiderabile.
-- 
-riko

 diverse estensioni.
Vorrei attaccarmi alla conclusione del vostro discorso.
Nel campo della programmazione ci sono tanti ambiti "estremi". Ci sono
ambienti dove la memoria e' un lusso assoluto che non si puo' pagare,
altri in cui il problema e' lavorare con team enormi fatti di scimmie
sapienti, altri ancora in cui il problema e' ragionare con codice legacy
senza documentazione. Ci sono quelli in cui il problema e' l'efficienza
CPU bound del singolo nodo, altri in cui e' il throughput, altri in cui
il gioco e' parallelizzare sempre CPU bound. Altri ambiti paralleli
(normalmente chiamati distribuiti) riguardano invece computazioni
essenzialmente I/O bound. Hai sistemi in cui i nodi comunicano su
infiniband, altri in cui hai in mezzo internet.
Tipicamente applicare i discorsi validi e sacrosanti per uno di questi
ambiti a tutto il mondo della programmazione provoca mostri. Ambiti,
requisiti, persone diverse. Tutto diverso.
In particolare i compilatori sono noti per fare particolarmente cacare
nel parallelizzare il codice. Non a caso tu scrivi codice esplicitamente
parallelo, non "speri" che il compilatore parallelizzi un for che lavora
su un vettore. Quel tipo di ottimizzazioni non si riescono a fare (e te
lo dico, perche' per un pochetto feci ricerca nell'ambito dell'analisi
statica... non ci si cava ragno dal buco).
Questo non vuole dire che *normalmente* il compilatore faccia un ottimo
lavoro. Fa un lavoro anche migliore degli umani sul codice CPU bound
singolo nodo (e dove la parallelizzazione non e' massiccia, vale lo
stesso discorso). Si puo' dire che, nella maggior parte dei casi, il
compilatore vince.
Puoi *aiutare* il compilatore. Sapendo come funziona, puoi evitare di
mettergli i bastoni fra le ruote, per esempio. Esattamente come eviterai
allocazioni e deallocazioni in un tight loop. Ma per il resto, nel 95%
dei casi, devi scrivere codice *buono*.
Tra l'altro ho spesso messo le mani in codice scientifico. Spesso e
volentieri faceva cacare: si vedavano stili che avevano senso, forse,
sulle macchine di una volta con compilatori di una volta. Oggi e' brutto
e basta.
Oppure prendi il codice di esempio di Quinn... il termine che userei e'
imbarazzante. Ok, li il punto era un altro. Questo non toglie che uno
che scrive codice del genere non lo vorrei in un team generico, a meno
che non e' provato che "o lo fai cosi' o non ci cavi quello che devi". 
-- 
-riko