Шрифт:
Для определения переменной указателя используется оператор *:
Приведенная запись означает, что переменная ptr содержит в себе адрес старшего байта двухбайтовой переменной типа int. Переменная указатель может быть определена для адресации различных типов переменных: целочисленных однобайтовых типа char и двухбайтовых типа int, одномерных и многомерных массивов из переменных char или int, одиночных переменных или массивов из элементов в формате с плавающей запятой, а также для структур, определенных пользователем. Спецификация типа указателя информирует компилятор о размере и типе объекта, на который показывает указатель. Таким образом, при обращении к любой области памяти через указатель, содержимое этой области будет трактоваться в соответствие с заданным типом указателя. В микроконтроллерах, поддерживающих различные способы формирования адресов объектов, спецификация типа может влиять на размер области памяти, отводимой для хранения указателя.
Применение указателей в реальных программах требует особого внимания программистов, поскольку именно с указателями связано основное количество ошибок в исходном тексте программы на Си. При манипулировании указателями, а также при выполнении операций присваивания следует убедиться в корректном использовании различных типов переменных. Приведем пример применения указателя:
В этом примере переменная ptr была определена как указатель для однобайтовой переменной типа char. Поэтому переменная ptr должна содержать 16 разрядный адрес однобайтовой переменной. В строке 4 примера был определен и инициализирован массив однобайтовых переменных message. Этот массив содержит 22 элемента: 21 символ в кодах ASCII и один байт признака конца строки. Выражение в строке 5 имеет своей целью запись в переменную ptr начального адреса массива message, т.е. адреса символа «W». Выражение, записанное в строке 6, должно начать вывод на экран монитора символа, на который указывает содержимое переменной указателя ptr. В строке 5 данного примера может быть записано другое, более понятное выражение:
В этом выражении символ «&» выполняет операцию взятия адреса первого элемента массива message. И именно эта функция была реализована нами в строке 5 исходного примера.
Выполняемое в рассмотренном выше программном фрагменте действие, может быть оформлено на Си другим образом, без использования указателя:
Обратите внимание, что в данном примере внутренняя переменная цикла i принимает значения от 0 до 20 включительно, выводя при этом на экран 21 символ. Приведенный способ реализации задачи вывода на экран строки символов обладает одним существенным недостатком. При смене числа символов в записи, выводимой на экран, придется написать новый фрагмент кода. Указанный недостаток исправлен в следующем программном фрагменте:
В этом примере указатель ptr используется для передачи в функцию putchar одного кода символа, который будет выведен на экран. Далее содержимое ptr увеличивается на 1, адресуя тем самым следующий элемент массива. По условию цикла while вывод на экран закончится, если в последовательно перебираемом массиве будет найден код конца строки.
Во встраиваемых системах указатели используются для обращения к регистрам специальных функций микроконтроллера. Рассмотрим следующую запись:
Эта запись информирует компилятор о том, что однобайтовая целочисленная переменная с именем PORTA располагается в памяти по адресу 0x1000. Служебное слово volatile информирует программу (и отладчик) о том, что значение PORTA может изменяться не только под управлением программы. Любое упоминание имени PORTA далее по тексту программы будет связано с выполнением операций чтения или записи в регистр данных PORTA по его физическому адресу 0x1000. Поэтому следующий программный фрагмент позволит прочитать содержимое порта PORTA в переменную new_value:
3.12. Структуры
Возможности языка Си позволяют объединить под одним именем переменные с разным форматом представления данных. Для этого используется понятие структуры.
Структура — это объект, состоящий из данных различных типов. При использовании структур следует различать объявление (или описание) структуры, как нового типа данных, например тип данных «структура x», от фактического определения некоторой переменной с типом данных «структура x». Пример объявления структуры типа car: