C, PHP, VB, .NET

Дневникът на Филип Петров


* Защо първият елемент на масив е с индекс 0?

Публикувано на 12 февруари 2026 в раздел С/С++.

Когато обясняваме за масиви и адресиране на елементите им, трябва да накараме учениците да осъзнаят, че използването на името на променливата е всъщност препратка към адреса на първия елемент на масива. Обясняваме им, че обръщането към arr[2] реално извършва чисто математическа операция, която е *(arr+2). Първото, с което обикновено се започва, е демонстрирането на това какво всъщност съдържа променливата arr:

int arr[3];
printf("%d\n", arr);

Вижда се някакво голямо число - именно това е адреса на първия елемент на масива в паметта. Тогава какво става ако прибавим единица към това число? Досетихте се - преминава се към следващия елемент. Това може да се покаже чрез следния пример. Макар всички тези „гимнастики“ в кода да са много лоша практика, идеята тук не е да се пише код по този начин, а да се осъзнае математиката зад кода:

int arr[4];
arr[0] = 1;
*(arr + 1) = 5; // същото като arr[1] = 5
*(2 + arr) = 6; // събирането е комутативна операция
3[arr]=9; // същото като *(3 + arr) = 9
arr[1]++;
2[arr]++; // същото 
printf("%d\n", arr[1]);
printf("%d", *(arr + 2));
return 0;

От този примери се вижда веднага, че arr[2], *(arr+2), *(2+arr) и съответно 2[arr] са едно и също нещо - те дават просто математическа сметка. И точно оттук идва и причината първият елемент на масив да е с индекс 0, а не 1. Ако беше 1, трябваше винаги да вадим една единица в сметката, а оттам има една математическа операция в повече. Хората, които са създали езика, са решили, че е по-добре тази операция да бъде спестена. За сметка на това програмистите е трябвало да свикнат, че адресацията на елементи започва от 0.

Със сигурност след тази демонстрация не използвайте никога алтернативните изписвания. В частност замяната на arr[i][j] с i[arr][j], j[i][arr] или i[j][arr] е категорично абсурдно.

Тук е момента да обясним един специфичен детайл - има разлика между arr и &arr. Макар и първоначално да изглежда все едно те съдържат едно и също нещо (следния код ще отпечата един и същи адрес):

int arr[3];
printf("%d\n", arr);
printf("%d\n", &arr);

има една съществена разлика - arr в случая е от тип int, докато &arr е от тип int[3]. Това може да се демонстрира лесно чрез следния код:

printf("%d\n", arr+1);
printf("%d\n", &arr+1);

Първият ред ще отпечата адреса на втория елемент на масива, докато втория ред ще отпечата един елемент след края на масива.

 



Добави коментар

Адресът на електронната поща няма да се публикува


*