C O D E - I N F O . R U

Си: Указатели, массивы, строки


Базовые понятия указателей, массивов и строк в языке программирования Си. Кратко и понятно.
Указатели и операции над ними

Указатель - это переменная, в которой хранится адрес!
Утверждение типа А указывает на Б означает А содержит адрес Б!


Описание переменных - указателей (адресный тип):
int *p;
double *q;


звёздочка воспринимается компилятором как атрибут описываемого имени, а не как часть типа:
char *s1, *s2, *s3; // указатели типа char
int x; // переменная типа int
int *p;  // указатель типа int


Операция взятия адреса "&":
p = &x; // заносим адрес x в указатель p
*p = 27; // занесёт 27 в область памяти типа int, т.е. в переменную x


Операция разименовывания "*":
x = 15;
*p; // - представляет из себя то, на что указывет p, то есть переменную x (15)


Тип указателя "void*":
Работа с адресами БЕЗ уточнения, на переменные какого типа эти адреса будут указывать:
если описать указатель такого типа:

void *z;
то в переменную z можно будет занести совершенно любой адрес.

Срециальное "адресное" значение ("нулевой указатель"):
(хотя на самом деле это адрес а не указатель).
Специальное обозначение такого адресного значения - идентификатор NULL:

int *p = NULL;
void *z = NULL;

NULL - имеет логическое значение "ложь", а любой другой адрес - "истина"


Массивы

int m[20]; // описание массива из 20 элементов типа int
int *p;

Каждый элементмассива доступен в отдельности.
Обратиться к массиву как к единому целому - НЕВОЗМОЖНО!!!


m - это адрес первого элемента массива
p = m; // и слева и справа один и тот же тип int*
после такого присваивания:
p[0] == m[0]; p[1] == n[1] ...

так как m - это адрес, к нему можно применить операцию разименовывания, то есть, обратиться к первому элементу можно не только через индексирование:
m[0]
но и иначе:
m*

индексирование в Си это операция не над массивами, а над адресами !!!


Если к типизированному адресному выражению (кроме void*) прибавить целое число, ТО ЭТОТ АДРЕС ИЗМЕНИТСЯ НА РАЗМЕР ЭЛЕМЕНТА ТОГО ТИПА, НА КОТОРЫЙ УКАЗЫВАЕТ ИСХОДНЫЙ АДРЕС !!!
char* + 1 // адрес увеличится на единицу;
так как размер элемента типа char, равен одному байту.
int* + 1 // адрес увеличится на 4;
так как размер элемента типа int, равен четырём байтам.
следовательно:

при добавлении единицы к адресу любого элемента массива, получаем адрес следующего элемента.

m; // адрес первого элемента
m + 1; // адрес второго, и т.д.


Коль это адреса, обращаться к ним можно через разименовывание:
*m, *(m+1), *(m+2), ..., *(m+19);
это, то же самое, что:
m[0], m[1], m[2], ..., m[19]
a[b] == *(a+b);


Операция sizeof()
sizeof(m); //выдаст размер массива целиком, в байтах (int m[20] = 80 байт)

Массив нельзя присвоить (следствие недоступности массива как единого объекта)
Стороки - тоже не присваиваются (т.к. частный случай массива)


Операция ВЫЧИТАНИЯ ТИПИЗИРОВАННЫХ АДРЕСОВ
Применяется к адресам одного массива.
Её результат - РАССТОЯНИЕ МЕЖДУ ДВУМЯ ЭЛЕМЕНТАМИ, Т.Е. РАЗНОСТЬ ИХ ИНДЕКСОВ
например если:
p = &m[13];
или просто:
p = m + 13;
то значением выражения p - m будет число 13
эта операция обратна операции прибавления целого числа к адресу.






 

Техническая


Понедельник 02 июля 2018

[Просмотров: 328]

Источник: code-info.ru