Come è stato notato, ci sono due scuole di pensiero su questo.
1) Dichiarare tutto al top delle funzioni perché l'anno è il 1987.
2) Dichiarare il più vicino al primo utilizzo e nel più piccolo ambito possibile.
La mia risposta a questa è DO ENTRAMBE! Lasciatemi spiegare:
Per le funzioni lunghe, 1) rende molto difficile il refactoring. Se lavori in una base di codice in cui gli sviluppatori sono contrari all'idea delle subroutine, allora avrai 50 dichiarazioni variabili all'inizio della funzione e alcune potrebbero essere solo una "i" per un for-loop che è proprio parte inferiore della funzione.
Da questo ho quindi sviluppato la dichiarazione al vertice del PTSD e ho provato a fare l'opzione 2) religiosamente.
Sono tornato all'opzione 1 per una cosa: funzioni brevi. Se le tue funzioni sono abbastanza brevi, allora avrai poche variabili locali e poiché la funzione è breve, se le metti in cima alla funzione, rimarranno comunque vicine al primo utilizzo.
Inoltre, l'anti-pattern di "declare e impostato su NULL" quando si desidera dichiarare in alto ma non sono stati effettuati alcuni calcoli necessari per l'inizializzazione viene risolto perché le cose che è necessario inizializzare verranno probabilmente ricevute come argomenti.
Quindi ora il mio pensiero è che dovresti dichiarare in cima alle funzioni e il più vicino possibile al primo utilizzo. Quindi ENTRAMBI! E il modo per farlo è con subroutine ben divise.
Ma se stai lavorando su una funzione lunga, metti le cose più vicine al primo utilizzo perché in questo modo sarà più facile estrarre i metodi.
La mia ricetta è questa Per tutte le variabili locali, prendi la variabile e sposta la sua dichiarazione verso il basso, compila, quindi sposta la dichiarazione appena prima dell'errore di compilazione. Questo è il primo utilizzo. Fallo per tutte le variabili locali.
int foo = 0;
<code that uses foo>
int bar = 1;
<code that uses bar>
<code that uses foo>
Ora, definisci un blocco ambito che inizia prima della dichiarazione e sposta la fine fino alla compilazione del programma
{
int foo = 0;
<code that uses foo>
}
int bar = 1;
<code that uses bar>
>>> First compilation error here
<code that uses foo>
Questo non viene compilato perché c'è altro codice che utilizza foo. Possiamo notare che il compilatore è stato in grado di esaminare il codice che utilizza bar perché non utilizza foo. A questo punto, ci sono due scelte. Quello meccanico è semplicemente spostare "}" verso il basso fino a quando non viene compilato, e l'altra scelta è ispezionare il codice e determinare se l'ordine può essere modificato in:
{
int foo = 0;
<code that uses foo>
}
<code that uses foo>
int bar = 1;
<code that uses bar>
Se l'ordine può essere cambiato, è probabilmente quello che vuoi perché accorcia la durata dei valori temporanei.
Un'altra cosa da notare, il valore di foo deve essere preservato tra i blocchi di codice che lo usano, o potrebbe essere solo un foo diverso in entrambi. Per esempio
int i;
for(i = 0; i < 8; ++i){
...
}
<some stuff>
for(i = 3; i < 32; ++i){
...
}
Queste situazioni richiedono più della mia procedura. Lo sviluppatore dovrà analizzare il codice per determinare cosa fare.
Ma il primo passo è trovare il primo utilizzo. Puoi farlo visivamente, ma a volte è più semplice eliminare la dichiarazione, provare a compilare e rimetterla al di sopra del primo utilizzo. Se il primo utilizzo si trova all'interno di un'istruzione if, inseriscilo e verifica se viene compilato. Il compilatore identificherà quindi altri usi. Prova a creare un blocco ambito che comprenda entrambi gli usi.
Dopo aver eseguito questa parte meccanica, diventa più semplice analizzare la posizione dei dati. Se una variabile viene utilizzata in un blocco di ambito di grandi dimensioni, analizzare la situazione e vedere se si sta utilizzando la stessa variabile per due cose diverse (come una "i" che viene utilizzata per due per i loop). Se gli usi non sono correlati, creare nuove variabili per ciascuno di questi usi non correlati.