Il FORTRAN vecchio stile richiedeva che un programmatore che desiderasse rendere disponibile una parte di un array per una funzione necessaria per passare un riferimento all'intero array, insieme a uno o più valori interi che specificano il pedice iniziale e il pedice finale o il numero di elementi . C rende possibile semplificare questo passaggio di un puntatore all'inizio della porzione di interesse insieme al numero di elementi. In termini diretti, ciò renderebbe le cose più veloci (passando due cose anziché tre). Indirettamente, tuttavia, potrebbe finire per rallentare le cose limitando i tipi di ottimizzazione che un compilatore può eseguire.
Considera la funzione:
void diff(float dest[], float src1[], float src2[], int n)
{
for (int i=0; i<n; i++)
dest[i] = src1[i] - src2[i];
}
se un compilatore sapesse che ciascuno dei puntatori identificherebbe l'inizio di un array, potrebbe generare codice che agirebbe su elementi dell'array in parallelo o in qualsiasi ordine, poiché per qualsiasi x! = y, operazioni su dest [x ] non influenzerà src1 [y] né src2 [y]. Ad esempio, su alcuni sistemi un compilatore può trarre vantaggio dalla generazione di codice equivalente a:
void dif(float dest[], float src1[], float src2[], int n)
{
int i=0;
float t1a,t1b,t2a,t2b,tsa,tsb;
if (n > 2)
{
n-=4;
t1a = src1[n+3]; t1b = src2[n+3]; t1b=src2[n+2]; t2b = src2[n+2];
do
{
tsa = t1a-t2a;
t1a = src1[n+1]; t2a = src2[n+1];
tsb = t2b-t2b;
dest[n+3] = tsa;
t1b = src1[n]; t2b = src2[n];
n-=2;
dest[n+4] = tsb;
} while(n >= 0);
... add some extra code to handle cleanup
}
else
... add some extra code to handle small values of n
}
Si noti che ogni operazione che carica o calcola un valore ha almeno un'altra operazione tra essa e l'operazione successiva che utilizza quel valore. Alcuni processori possono sovrapporsi al trattamento di diverse operazioni quando tali condizioni sono soddisfatte, migliorando così le prestazioni. Si noti, tuttavia, che poiché un compilatore C non ha modo di sapere che il codice non passerà i puntatori alle aree parzialmente sovrapposte di un array comune, un compilatore C non può effettuare la trasformazione sopra. I compilatori FORTRAN con un codice equivalente, tuttavia, potevano e hanno fatto una tale trasformazione.
Mentre un programmatore C potrebbe tentare di ottenere prestazioni comparabili scrivendo esplicitamente il codice che ha srotolato il loop e si è sovrapposto alle operazioni dei passaggi adiacenti, tale codice potrebbe facilmente degradare le prestazioni se usasse così tante variabili automatiche che un compilatore ha dovuto "riversarle" in memoria. L'ottimizzatore di un compilatore FORTRAN probabilmente saprebbe più di un programmatore su quali forme di interfogliatura produrrebbero prestazioni ottimali in un dato scenario, e tali decisioni sono spesso meglio lasciare a tali compilatori. Mentre C99 ha tentato di migliorare in qualche modo la situazione di C aggiungendo un restrict
qualificatore, questo può essere usato qui solo se dest[]
era un array separato da entrambi src1[]
e src2[]
, o se il programmatore ha aggiunto versioni separate del ciclo per gestire i casi in cui tutto dest
era disgiuntosrc1
e src2
, dove src1[]
ed dest
erano uguali ed src2
era disgiunto, dove src2[]
ed dest[]
erano uguali ed src1
era disgiunto, e dove tutte e tre le matrici erano uguali. FORTRAN, al contrario, potrebbe gestire tutti e quattro i casi senza difficoltà usando lo stesso codice sorgente e lo stesso codice macchina.