Указатели на базовые типы данных

ЛЕКЦИЯ № 6

«Использование указателей в программах
на языках С / С++ (часть 1)

 

по курсу «Структуры и алгоритмы обработки данных»

(для специальности «Управление в технических системах»)

 

СОДЕРЖАНИЕ

 

6.1. Указатели на базовые типы данных

6.2. Основные операции, связанные с применением указателей

6.3. Указатель на неопределенный тип данных

6.4. Указатели на структурные переменные и объекты классов

6.5. Указатели на функции

 

ВВЕДЕНИЕ

 

Применение языков программирования С/C++ наиболее эффективно для решения задач системного программирования и для разработки различных инструментальных средств. Данные языки позволяют осуществлять работу с адресами памяти компьютеров через специальные переменные, называемые указателями. Поэтому свободное владение механизмом применения указателей является одним из ключевых моментов разработки сложных и эффективных программ.

Данная работа состоит из трех разделов. Первый раздел посвящен применению указателей при разработке программ для OS Windows. При разработке таких программ в подавляющем числе приложений используется уже не язык С, а его наследник С++. Однако механизм применения указателей в программах одинаков в обоих языках.

Второй раздел посвящен применению указателей при разработке программ для OS DOS. Применение указателей при разработке DOS- программ имеет некоторые особенности, которые полезно знать. В частности, при написании программ, требующих монопольного использования процессора (однозадачный режим).

Третий раздел посвящен применению указателей при разработке программ на языке C# для платформы .NET. Здесь применение указателей весьма специфично.

 

Указатель - это поименованный адрес памяти компьютера. Это означает, что в Си – программах адресам переменных могут быть даны имена, что позволяет обращаться к переменным, используя их символическое обозначение. К примеру, адрес здания по проспекту Ленина, д. 25 имеет имя: корпус «ХТ ТГТУ». Использование имени часто оказывается более удобным, чем использование адреса.

Для примера рассмотрим следующую Си - программу.

 

/* программа # 1.1 */

void main( void )

{

char Ch;

int count;

}

В программе объявлено две переменных: первая символьного типа, а вторая целого. Для первой переменной при компиляции программы будет выделен один байт, а для второй - четыре байта памяти (в 32–х разрядной машине). Для того чтобы узнать адрес байта переменной Ch и адрес первого байта переменной count, необходимо объявить два указателя и присвоить им адреса соответствующих переменных, как показано в программе #1.2:

 

/* программа # 1.2 */

void main ( void )

{

char Ch, *point_Ch;

int count,*point_count;

 

Ch = 'T';

count = 0;

point_Ch = &Ch; // операция получения адреса и инициализация указателя

point_count =&count; // операция получения адреса и инициализация указателя

 

return;

}

 

Приведенные объявления в программе читаются следующим образом: point_Ch есть указатель на тип сhar. Переменная point_count есть указатель на тип int. Указатель может быть объявлен на любой тип данных без исключения. Это может быть структура, класс, функция, объединение и пр.

Выбор имен (идентификаторов) указателей дело программиста. Обязательным является символ '*' перед именем идентификатора. Именно этот символ характеризует данную переменную как указатель. При компиляции программы будет выделена память для хранения двух адресов. В 32 – разрядной машине это - 4 байта независимо от того, с каким типом данных будет работать указатель.

Символ '&', стоящий перед именем переменной, означает операцию получения адреса этой переменной. В двух последних операторах программы переменной point_Ch присваивается адрес переменной Ch, а переменной point_count - адрес переменной count. Другими словами, в двух последних операторах выполняется инициализация указателей. Теперь адрес переменной Ch имеет имя point_Ch, а переменной count - point_count.

 

Для того чтобы узнать адреса переменных Ch и count, усложним программу.

 

/* программа # 1.3 */

# include <stdio.h>

void main ( void )

{

char Ch, *point_Ch; int count,*point_count;

 

Ch = 'T';

count = 0;

point_Ch = &Ch;

point_count =&count;

printf("Адрес переменной Ch = %08X \n",point_Ch);

printf("Адрес переменной count = %p \n",point_count);

}

 

В начале поясним, что означает спецификация формата 0Х8 в первом операторе printf. 0 - напечатать ведущие (незначащие) нули в адресе. 8Х- отвести 8 позиции для выдачи на экран значения адреса, которое должно быть представлено шестнадцатеричным числом. Х прописное означает, что если в шестнадцатеричном числе имеются символы, то они должны быть напечатаны прописными буквами. Во втором операторе printf используется спецификация формата p, которая специально предназначена для печати адресов. Адрес самого указателя также может быть получен через операцию &. Например, с помощью оператора программы

 

printf("Адрес переменной point_Ch = %08X\n",&point_Ch);

 

На экран будет выведен адрес самого указателя point Ch (точнее адрес первого байта, поскольку самая переменная 4-x байтная).