FORTRAN vecchio stile richiedeva che un programmatore che voleva rendere parte di un array disponibile per una funzione necessitasse di passare un riferimento all'intero array, insieme a uno o più valori interi che specificano il pedice iniziale e l'indice finale o numero di articoli. C rende possibile semplificare questo passaggio al puntatore all'inizio di la parte 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 sapeva che ognuno dei puntatori avrebbe identificato l'inizio
di un array, potrebbe generare un codice che agisca su elementi del
array in parallelo, o in qualsiasi ordine, poiché per qualsiasi x! = y, operazioni attive
dest [x] non influenzerà src1 [y] né src2 [y]. Ad esempio, su alcuni sistemi
un compilatore può trarre beneficio 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 questa e l'operazione successiva che utilizza quel valore. Alcuni processori possono sovrapporsi all'elaborazione 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 verrà passato puntatori a regioni parzialmente -overlapping di un array comune, un compilatore C non può effettuare la trasformazione di cui sopra . I compilatori FORTRAN dati un codice equivalente, tuttavia, potevano e facevano una tale trasformazione.
Mentre un programmatore C poteva tentare di ottenere prestazioni comparabili scrivendo esplicitamente il codice che srotolava il ciclo e sovrapponeva le operazioni dei passaggi adiacenti, tale codice poteva facilmente degradare le prestazioni se utilizzava così tante variabili automatiche che un compilatore doveva "spargere" "loro alla memoria. Un ottimizzatore del compilatore FORTRAN probabilmente conoscerebbe più di un programmatore su quali forme di interleaving offrirebbero prestazioni ottimali in un dato scenario e tali decisioni sono spesso lasciate a tali compilatori. Mentre C99 ha tentato di migliorare un po 'la situazione di C aggiungendo un qualificatore restrict
, potrebbe essere usato qui solo se dest[]
era un array separato da src1[]
e src2[]
, o se il programmatore ha aggiunto versioni separate del ciclo per gestire i casi in cui tutto dest
era disgiunto da src1
e src2
, dove src1[]
e dest
erano uguali e src2
era disgiunto, dove src2[]
e dest[]
erano uguali e src1
era disgiunto e dove tutti e tre gli array erano uguali. FORTRAN, al contrario, potrebbe gestire tutti e quattro i casi senza difficoltà utilizzando lo stesso codice sorgente e lo stesso codice macchina.