
- •Конструкция else if
- •Рассмотрим интересные условные выражения с использование логических операторов.
- •Циклы for, while и do while в языке c
- •Функции в языке программирования c
- •Указатели в c
- •Что такое указатели и зачем они нужны?
- •Объявление указателя, получение адреса переменной
- •Выделение памяти в Си (функция malloc)
- •Динамическое выделение памяти в c
- •Выделение памяти в Си (функция malloc)
- •Структуры в языке с
- •Массивы в c (часть 1)
Указатели в c
Указатели это чрезвычайно мощный инструмент в программировании. С помощью указателей некоторые вещи в программировании можно сделать намного проще и при этом эффективность работы вашей программы значительно повысится. Указатели даже позволяют обрабатывать неограниченное количество данных. Например, с помощью указателей можно изменять значения переменных внутри функции, при этом переменные передаются в функцию в качестве параметров. Кроме того, указатели можно использовать для динамического выделения памяти, что означает, что вы можете писать программы, которые могут обрабатывать практически неограниченные объемы данных на лету — вам не нужно знать, когда вы пишете программу, сколько памяти нужно выделить заранее. Пожалуй, это самая мощная функция указателей. Для начала давайте просто получим общее представление об указателях, научимся их объявлять и использовать.
Что такое указатели и зачем они нужны?
Указатели похожи на метки, которые ссылаются на места в памяти. Представьте сейф с депозитными ячейками различного размера в местном банке. Каждая ячейка имеет номер, уникальный номер, который связан только с этой ячейкой, таким образом можно быстро идентифицировать нужную ячейку. Эти цифры аналогичны адресам ячеек компьютерной памяти. К примеру, у вас есть богатый дядя, который хранит все свои ценности в своем сейфе. И чтобы обезопасить все свои сбережения, он решил завести меньший сейф, в который положит карту, на которой показано местоположение большого сейфа и указан 16-й пароль от большого сейфа, в котором и хранятся реальные драгоценности. По сути, сейф с картой будет хранить расположение другого сейфа. Вся эта организация сбережения драгоценностей эквивалентна указателям в языке Си. В компьютере, указатели просто переменные, которые хранят адреса памяти, как правило, адреса других переменных.
Идея в том, что зная адрес переменной, вы можете пойти по этому адресу и получить данные, хранящиеся в нем. Если вам нужно передать огромный кусок данных в функцию, намного проще передать адрес в памяти, по которому хранятся эти данные, чем скопировать каждый элемент данных! Более того, если программе понадобится больше памяти, вы можете запросить больше памяти из системы. Как же это работает? Система просто возвращает адрес ячейки памяти, и мы должны сохранить этот адрес в переменной-указателе. Так мы сможем взаимодействовать с данными из указанного участка памяти.
Синтаксис указателей
Если у нас есть указатель, значит мы можем получить его адрес в памяти и данные на которые он ссылается, по этой причине указатели имеют несколько необычный синтаксис, отличающийся от объявления простых переменных. Более того, поскольку указатели — это не обычные переменные, то, необходимо сообщить компилятору, что переменная является указателем, и сообщить компилятору, тип данных, на которые ссылается указатель. Итак, указатель объявляется следующим образом:
1 |
data_type *pointerName; |
где, data_type — тип данных, pointerName — имя указателя.
Например, объявим указатель, который хранит адрес ячейки памяти, в которой лежит целое число:
1 |
int *integerPointer; |
Обратите внимание на использование символа *, при объявлении указателя. Этот символ является ключевым в объявлении указателя. Если в объявлении переменной, непосредственно перед именем переменной, добавить этот символ, то переменная будет объявлена как указатель. Кроме того, если вы объявляете несколько указателей в одной строке, каждый из них должен предваряться символом звездочки. Рассмотрим несколько примеров:
1 2 3 4 5 6 7 |
// Объявление указателя и простой переменной в одной строке int *pointer1, // это указатель variable; // это обычная переменная типа int
// Объявление двух указателей в одно строке int *pointer1, // это указатель с именем pointer1 *pointer2; // это указатель с именем pointer2 |
Как я и говорил, если имя переменной не предваряется символом *, то это обычная переменная, в противном случае — это указатель. Именно это и показывает пример объявления указателей, выше.
Есть два способа использования указателя:
Использовать имя указателя без символа *, таким образом можно получить фактический адрес ячейки памяти, куда ссылается указатель.
Использовать имя указателя с символом *, это позволит получить значение, хранящееся в памяти. В рамках указателей, у символа * есть техническое название — операция разименования. По сути, мы принимаем ссылку на какой-то адрес памяти, чтобы получить фактическое значение. Это может быть сложно для понимания, но в дальнейшем постараемся разобраться во всем этом.