![float:right|](52226.png) Если несколько переменных имеют одинаковое назначение в программе, с ними производятся одинаковые действия (семь козлят или семь гномов в сказках), то вместо задания каждой переменной уникального имени мы указываем имя для всего набора таких переменных и их количество:
`"тип" quad "имя"` ``[`` `"количество"` ``];``
Для доступа к элементам такого набора используется операция индексации: `"имя" [ "номер" ]`, где `"номер"` принимает значения от 0 до `("количество"-1)`.
Набор из элементов одинакового типа, обращение к которым идет по их порядковому номеру (*индексу*), называется *массив*. Аналогом массива в математике является последовательность, но массив всегда имеет ограниченный размер, а последовательность в математике часто является бесконечной.
Для заполнения и обработки массивов используются циклы.
Так как операция индексации в языке С не проверяет выход номера за границы, рекомендуется самостоятельно проверять, что первое и последнее значение переменной цикла не приводит в операции индексации к получению значения меньше 0 или больше `("количество"-1)`.
```run-c
#include <stdio.h>
// Факториалы целых чисел
int main()
{ int f[13];
f[0]=1;
for(int i=1; i<13; ++i)
f[i]=i*f[i-1];
for(int i=0; i<13; ++i)
printf("%d! = %d\n",i,f[i]);
}
```
В программе несколько раз повторяется число 13. При изменении размера массива придется изменить эти константы на другое значение столько же раз. Для упрощения таких изменений можно
* использовать операцию ``sizeof``, которая возвращает размер в байтах своего аргумента -- для получения количества элементов в массиве ``f`` нужно написать ``sizeof(f)/sizeof(f[0])``
* определить именованную константу, используя команду *препроцессора*\
``#define `` `"имя" quad "значение"`
Имя такой константы рекомендуется писать прописными буквами.
```run-c
#include <stdio.h>
// Решето Эратосфена для простых чисел
#define N 1000000
char p[N+1];
int main()
{ p[0]=p[1]=1; // 0 и 1 не являются простыми
for(int i=2; i*i<=N; ++i)
if(!p[i]) { // не вычеркнуто
for(int j=i*i; j<=N; j+=i)
p[j]=1; // вычеркнуть числа, кратные i
}
int k=0;
for(int i=1; i<=N; ++i)
if(!p[i]) ++k;
printf("Количество простых числе от 1 до %d равно %d\n",N,k);
}
```
Без инициализации элементы массива, определяемого в стековой памяти, имеют неопределенное значение, в статической -- 0.
Можно указать начальные значения элементам массива, количество элементов которого задано константой. Список начальных значений указывается в ``{}`` через запятую, начиная с нулевого. Можно явно указать, какому элементу присваивается значение: `[ "номер" ]="выражение"`. Если значение какого-либо элемента явно не указано, то он получает значение 0. Если количество элементов в массиве определяется списком инициализации, количество можно не указывать:
```c
int a[]={1,2,3,4,5};
```
```run-c
#include <stdio.h>
int a[10]; // статическая память, все элементы 0
int main()
{ int b[10]; // стековая память, неопределенное значение
int c[10]={1,2,7,[7]=100, [9]=101}; // стековая память,
// элементы с номерами 0,1,2,7,9 заданы явно, остальные - 0
for(int i=0; i<10; ++i)
printf("%d: %d %d %d\n",i,a[i],b[i],c[i]);
}
```
Для копирования элементов массива вместо цикла можно использовать функции ``memcpy`` и ``memmove``, объявленные в ``<string.h>``. ``memcpy`` позволяет скопировать один массив в другой (массивы должны быть одинакового типа и размера), ``memmove`` используется для копирования части массива, в том числе в пределах одного массива.
```run-c
#include <stdio.h>
#include <string.h>
int main()
{ int a[10]={1,2,3,4,5,6,7,8,9,10},
b[10];
memcpy(b,a,sizeof(a)); // b <- весь a
for(int i=0; i<10; ++i)
printf("%d%c",b[i],i<9?' ':'\n'); // вывод массива b
memmove(b+4,b+6,sizeof(b[0])*3); // b[4],b[5],b[6] <- b[6],b[7],b[8]
for(int i=0; i<10; ++i)
printf("%d%c",b[i],i<9?' ':'\n');
}
```