225.55K
Категория: ПрограммированиеПрограммирование

Массивы и указатели. Лекция 10

1.

Массивы и указатели

2.

Массивы
Массивы хранят элементы одного и того же базового типа (например, массив целых чисел, или
массив действительных чисел), доступ к которым осуществляется по их порядковым номерам.
Объявление массива:
тип ИмяМассива[размер];
Размер статического массива задается во время объявления и дальше уже не изменяется.
Доступ к элементу массива:
ИмяМассива[НомерЭлемента];
Инициализация элементов массива
int mas[5] = { 1, 2, 3, 4, 5 };
int mas[5] = { 1, 2 };
int mas[256] = { 0 }; - простой способ обнуления массива любого размера:
int mas[5] = { 1, 2, 3, 4, 5, 6, 7, 8 }; - ошибка компиляции.

3.

Массивы
В памяти компьютера массив представляет собой последовательность подряд идущих переменных
заданного типа. Нумерация элементов в массиве начинается с нуля.
Имя массива является указателем на его первый элемент (с номером 0).
int str[10] = {7,1,3,2,5,7,1,3,2,5};
int *p;
p=str; // эквивалентно p=&str[0];
Квадратные скобки в синтаксисе доступа к элементу массива преобразуются компилятором:
str[10] эквивалентно *(str+10) эквивалентно *(10+str) эквивалентно 10[str]
&str[0] эквивалентно &(*(str+0)) эквивалентно
&*str
эквивалентно str

4.

Массивы
Строка (строковый литерал) является разновидностью одномерного массива. Любая строка в Си
должна заканчиваться нуль-терминатором (ASCIIZ-формат), поэтому при объявлении строки
необходимо предусмотреть для него место.
char str[7] = {‘s’,’t’,’r’,’o’,’k’,’a’,’\0’};
char str[7] = “stroka”;
char str[] = “stroka”;
char *str = “stroka”;
char *str = {‘s’,’t’,’r’,’o’,’k’,’a’,’\0’}; // неверно!!!! только
строка в двойных кавычках может быть проинициализирована при объявлении
указателя.

5.

Массивы
Поэтому, если хотим использовать указатель при работе массивами, присваиваем ему адрес
первого элемента уже созданного массива:
char str[7] = {‘s’,’t’,’r’,’o’,’k’,’a’,’\0’};
int *p;
p=str; // эквивалентно p=&str[0];
Квадратные скобки в синтаксисе доступа к элементу массива преобразуются компилятором:
str[10] эквивалентно *(str+10) эквивалентно *(10+str) эквивалентно 10[str]
&str[0] эквивалентно &(*(str+0)) эквивалентно
&*str
эквивалентно str
Наряду со сходством имени массива и указателей между ними существует различие. Указатель - это
переменная и выражения вида p=str и p++ являются допустимыми. Имя массива - константа и
выражения str=p, str++, p=&str являются ошибочными, так как значение константы не может
быть изменено, константа является неадресуемой величиной (нельзя обратиться к ней по адресу).

6.

Массивы
#include <stdio.h>
void putstr(char *str);
int main()
{
char str[]="Stroka stroka";
putstr(str);
return 0;
}
Два способа обращения к элементам массива
Индексация
использование индекса
(дополнительная
переменная)
нагляднее
void putstr(char *str)
{
int i=0;
while (str[i]) putchar(str[i++]);
}
Адресная
арифметика
использование
операции *
эффективнее
void putstr(char *str)
{
while (*str) putchar(*str++);
}

7.

Многомерные массивы
Многомерный массив – это массив, элементами которого являются массивы. Размерность
массива – это количество индексов, используемых для доступа к его конкретному элементу.
int mas[5][15];
Константное выражение, определяющее одну из размерностей массива, не может принимать
нулевое значение:
int mas[0][7]; // ошибка
Инициализация двумерных массивов выполняется построчно, то есть в порядке возрастания
правого индекса. Именно в таком порядке элементы двумерных массивов располагаются в
памяти компьютера, например:
int mas[2][3]={2, 14, 36, 23, 1, 9};
Проинициализированный массив (матрица) будет выглядеть так:
0
1
0
1
2
2
23
14
1
36
9

8.

Многомерные массивы
Многомерные массивы могут инициализироваться и без указания одной (самой левой)
размерности массива. В этом случае количество элементов компилятор определяет по
количеству элементов в списке инициализации.
Например, для массива mas будет получен тот же, что и в предыдущем примере результат:
int mas[][3]={ 34, 23, 67,
38, 56, 73,
37, 94, 28 };
Если необходимо проинициализировать не все элементы строки, а только несколько первых
элементов каждой строки, то в списке инициализации можно использовать фигурные скобки,
охватывающие значения для этой строки, например:
int mas[][3]={ { 0 },
{ 10, 11},
{ 21, 21, 22} };

9.

Многомерные массивы
int mas[][3]={
34, 23, 67,
38, 56, 73,
37, 94, 28 };
использование mas эквивалентно &mas[0][0]
Правила адресной арифметики при адресации элементов многомерного массива требуют
приведения типа указателя на массив к его базовому типу.
mas[0][2] эквивалентно *((int*)mas+2)
mas[1][1] эквивалентно *((int*)mas+(1*3)+2) эквивалентно *((int*)mas+5)
mas[i][j]=*((тип*)mas+(i*кол_столбцов)+j)
Таким образом, двухмерный массив можно свести к указателю на одномерный массив.

10.

Массивы указателей
Кроме обычных массивов, в языке Си используются массивы указателей - массивы, элементами
которых являются указатели (например, на элементы другого массива).
Описание массива указателей имеет вид:
float *mas[6];
Это соответствует массиву из шести элементов, являющихся адресами объектов типа float.
Очевидные преимущества возникают, когда сами указуемые элементы являются достаточно
большими (массивы, строки, структуры и т.д.). Тогда изменение порядка следования
(включение, исключение, упорядочение, перестановка), которое в обычном массиве
заключается в перемещении самих элементов, в массиве указателей должно сопровождаться
соответствующими операциями над указателями.

11.

Многоуровневые указатели
double **pp;
pp нужно интерпретировать как переменную, при косвенном обращении к которой получается
указатель на переменную типа double, то есть как указатель на указатель или адрес указателя.
Но поскольку любой указатель в Си может ссылаться как на отдельную переменную, так и на
область памяти (массив), то в применении к двойному указателю получаются четыре варианта
структур данных, а именно:
указатель на одиночный указатель на переменную типа double;
указатель на одиночный указатель на массив переменных типа double;
указатель на массив, содержащий указатели на одиночные переменные типа double;
указатель на массив, содержащий указатели на массивы переменных типа double.
double **pp, *pd[20];
pp = pd;
*(pp+i)
**(pp+i)
// или pp = &pd[0];
// или pp[i]
// или *pp[i]
English     Русский Правила