Старий стиль FORTRAN вимагав, щоб програміст, який хотів зробити частину масиву доступною для функції, необхідної для передачі посилання на весь масив, разом з одним або декількома цілими значеннями, що вказують на початковий індекс та або закінчуючий індекс та кількість елементів . C дозволяє спростити це до передачі покажчика на початок цікавої частини разом із кількістю елементів. Прямо кажучи, це зробило б справи швидше (проходження двох речей, а не трьох). Однак опосередковано це може призвести до уповільнення речей, обмеживши види оптимізації, які може виконувати компілятор.
Розглянемо функцію:
void diff(float dest[], float src1[], float src2[], int n)
{
for (int i=0; i<n; i++)
dest[i] = src1[i] - src2[i];
}
якщо компілятор знав, що кожен з покажчиків ідентифікує початок масиву, він може генерувати код, який буде діяти на елементи масиву паралельно або в будь-якому порядку, оскільки для будь-яких x! = y операцій над dest [x ] не вплине на src1 [y] і src2 [y]. Наприклад, у деяких системах компілятор може отримати користь від генерування коду, еквівалентного:
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
}
Зауважте, що кожна операція, яка завантажує або обчислює значення, має принаймні ще одну операцію між нею та наступною операцією, яка використовує це значення. Деякі процесори можуть перекривати обробку різних операцій, коли такі умови виконуються, тим самим покращуючи продуктивність. Однак зауважте, що оскільки компілятор C не може знати, що код не буде переданий покажчиками на частково перекриваються регіони загального масиву, компілятор C не може здійснити вищевказане перетворення. Укладачі FORTRAN дали еквівалентний код, однак, могли б і зробити таке перетворення.
Хоча програміст C міг би спробувати досягти порівнянної продуктивності, явно виписавши код, який розкрутив цикл і перекрив операції суміжних проходів, такий код міг легко погіршити продуктивність, якщо він використовував би стільки автоматичних змінних, що компілятору довелося "розлити" їх на пам'ять. Оптимізатор компілятора FORTRAN, ймовірно, знає більше, ніж програміст про те, які форми переплетення дають оптимальну ефективність у визначеному сценарії, і такі рішення часто краще залишити таким компіляторам. У той час як C99 намагалися поліпшити ситуацію Кассіопеяна кілька, додавши restrict
специфікатор, який може бути використаний тільки тут , якщо dest[]
був окремий масив з обох src1[]
і src2[]
, або , якщо програміст додав окремі версії циклу для обробки випадків , коли всеdest
було НЕ перетинається зsrc1
і src2
, деsrc1[]
і dest
були рівними, і src2
були непересічними, де src2[]
і dest[]
були рівними, і src1
були непересічними, і де всі три масиви були рівними. FORTRAN, навпаки, може без проблем обробляти всі чотири випадки, використовуючи той самий вихідний код і той же машинний код.