Домашняя страница библиотеки_c AVR

Синтаксис языка C

Библиотека языка C GNU glibc

 Страницы развития библиотеки_с AVR

Главная страница

Инструкция пользователя

Содержание библиотеки_c

Часто задаваемые вопросы

Содержание по алфавиту

Демонстрационные проекты


 

Указатель — это переменная, содержащая адрес некоторого элемента данных (переменной, константы, функции, структуры). В языке C указатели тесно связаны с обработкой массивов и строк, которые будут рассмотрены в следующем разделе.

Для объявления переменной как указателя используется оператор *:

Для присвоения адреса некоторой переменной указателю используется опера­тор &, например:

char *p;                       // объявляем указатель (способен содержать адрес хранения любого символа);

char c = 'А';     // объявляем символьную переменную с;

р = &c;                       // теперь p содержит адрес хранения символа c.

 

Для того чтобы извлечь значение переменной, на которую указывает указа­тель, используется оператор разыменования *.

char *p;

char b; char c = 'А';

р = &c;.

b = *р;            // теперь b равняется не адресу хранения переменной c, а значению переменной c, то есть 'А'.

 

Аналогичным образом, этот оператор можно использовать и для присвоения некоторого значения переменной, на которую указывает указатель:

char *p;

char b, char c = 'А';

р = &b;           // теперь p содержит адрес хранения ещё не инициализированной переменной b;

*р = b;            // инициализируем переменную b значением 'А'.

 

Применительно к программированию микроконтроллеров, указатели можно использовать, к примеру, для записи данных в порт ввода/вывода. Предположим, регистр данных порта расположен в памяти по адресу 0x16. В этом случае, для записи в него значения 0xFF можно воспользоваться следующим фрагментом программного кода:

unsigned char *p;          //объявление указателя на символ

p = 0x16;         // присваиваем указателю адрес порта PORTx

*p = 0xFF;      // теперь на выводах порта PORTx будут все единицы.

 

Передача в функции параметров по ссылке.

С помощью указателей, используемых в качестве параметров функций, можно организовать возврат более одного значения. Рассмотрим следующий пример:

int SumAndDiv(int *a, int *b) /* Объявляем функцию, возвращающую сумму от целочисленного деления без                      остатка и остатка */

{

int bufA, bufB;               // Объявление целых чисел – bufA и bufB;

bufA = *a;         // bufA = значению, на которое указывает указатель а;

bufB = *b;         // bufB = значению, на которое указывает указатель b;

*a = bufA / bufB;           //Указатель a ссылается на результат целочисленного деления без остатка

*b = bufA % bufB;  //Указатель b ссылается на остаток от целочисленного деления

return bufA + bufB;  //Функция возвращает сумму

int vl, v2, sum;

vl   =   10;

v2   =   3;

sum  =   SumAndDiv(&vl,    &v2);         //sum  =   4;   vl   =   3;   v2   =   1.

В функции SumAndDiv вначале сохраняются в буферных переменных значе­ния, на которые указывают указатели а и b. Затем в переменную, на которую ука­зывает указатель а записывается результат деления переданных в функцию значе­ний без остатка, а в переменную, на которую указывается указатель b — остаток от такого деления. Поскольку с помощью указателей мы напрямую обращались к ячейкам памяти, а не к переменным, то после выхода из функции содержимое этих ячеек остается неизменным. При вызове функции SumAndDiv в нее переда­ются адреса переменных vl и v2, которым в теле функции соответствуют указате­ли а и b.

 

Указатели на структуры

На структуры можно создавать указатели точно так же, как и для любого дру­гого типа данных. Пример применения такого указателя:

Struct DATE

{

int Day;

int Month;

int Year;

}

struct   DATE  MyBirthday,    *dateP;

dateP  =   SMyBirthday;      //dateP  указывает   на   структуру MyBirthday

В таком случае для доступа к полям структуры через указатель используется onepaтор ->:

dateP->Day = 7;

dateP->Month = 8;

dateP->Year = 1974;

Можно также использовать и разыменование указателя:

(*dateP).Day = 7;

(*dateP).Month = 8;

(*dateP).Year = 1974;

ПРИМЕЧАНИЕ

В последнем примере операция *dateP заключена в скобки, поскольку оператор разыме­нования * имеет меньший приоритет по сравнению с оператором доступа к полю структуры.

 

Указатели также могут быть полями структуры. Это часто используется для создания в памяти цепочек однотипных структур, когда каждая предыдущая ука­зывает на следующую:

struct   DATE 

{

int   Day;

int Month;

int Year;

struct DATE *next_date; //указатель на другую структуру того же типа

}

struct   DATE  datel,   date2;

datel.next_date   =   &date2;

Теперь, к примеру, оператору datel.next_date->Year соответствует дос­туп к полю Year структуры date2 (то есть, это эквивалентно записи date2.Year).

 

Hosted by uCoz