Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DOROGOVA.pdf
Скачиваний:
245
Добавлен:
05.06.2015
Размер:
853.4 Кб
Скачать

Вопросы для самопроверки

1.Дайте общее определение массива данных.

2.Может ли массив содержать переменные нескольких типов?

3.Дайте определение статического массива данных.

4.Перечислите свойства статических массивов.

5.Приведите пример объявления статического массива.

6.Что такое индекс массива?

7.Приведите пример обращения к элементу массива.

8.Какова взаимосвязь между значением индекса и значением элемента массива?

9.Для чего нужна инициализация массивов?

10.Можно ли инициализировать массив при его объявлении?

11.Расскажите об одномерных и многомерных массивах их инициализация, обращение к элементам. Приведите примеры.

12.Что произойдет, если при обращении к элементу массива индекс превысит максимально возможное значение?

13.Что такое строка с языке С++?

14.Как присвоить значение строковой переменной?

PDF created with FinePrint pdfFactory Pro trial version http://www.fineprint.com

6. Указатели и ссылки

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

6.1. Понятие указателя

Определяя переменную, программист задает её имя, которое позволяет оперировать со значением переменной это программный уровень работы. На машинном уровне компьютер имеет дело с понятиями "адрес участка памяти", выделенный под переменную и "содержимое участка памяти".

Например, при определении переменной, выделяется необходимая память (допустим по адресу 100), а оператор присваивания заносит в неё некое значение.

int var =1;

Программный

Уровень

 

 

ИМЯ

ЗНАЧЕНИЕ

 

 

 

VAR

1

 

Машинный

 

 

Уровень

 

 

 

 

АДРЕС ПАМЯТИ

 

СОДЕРЖИМОЕ ПАМЯТИ

 

 

100

 

1

 

Можно сказать иначе, имя переменной var адресует участок памяти, а константа 1 определяет значение, которое запишется по этому адресу. Имея адрес переменной или другого объекта программы необходимо с ним работать: сохранять, передавать и преобразовывать, для этой цели и служат указатели.

Указатели это переменные, значениями которых являются адреса других объектов переменных, массивов, функций.

Указатели служат для обращения к области памяти, отведенной под другую переменную. Подобно любой другой переменной, указатель нужно создать (объявить) и задать начальное значение. Термин "задать значение" применительно к указателю используется редко, вместо этого говорят, что нужно "установить" указатель, после чего он будет "ссылаться", то есть указывать на переменную.

Чтобы создать указатель следует определить тип данных, на которые он будет ссылаться. Символ "*" сообщает компилятору, что вы создаете указатель, в конце указывается имя переменной.

Например, инструкция int *ptr; создает указатель, который будет ссылаться на данные целого типа.

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

// переменная ptr_i – указатель на данные типа int int *ptr_i ;

//переменная ptr_с указатель на данные типа char char *ptr_c ;

//переменая ptr_d – указатель на данные типа double double *ptr_d ;

6.2. Операция получения адреса &

После того, как указатель определен, его нужно установить на какой-либо объект, размещенный в памяти компьютера, то есть записать в него адрес этого объекта. Выражение &var позволяет получить адрес памяти, выделенный под переменную var. Следует отметить, что операция & применима только к объектам, имеющим имя и размещенным в памяти.

Операцию & нельзя применять к:

выражениям;

константам;

битовым полям;

регистровым переменным;

внешним объектам (файлам).

PDF created with FinePrint pdfFactory Pro trial version http://www.fineprint.com

Неправильными являются конструкции: &(х+7) и &28.

Первая пытается получить адрес выражения, а вторая константы.

Установка указателя на объект это обязательный этап работы. Будьте внимательны неустановленный указатель главный источник неприятностей. Если переменная p объявлена как указатель, то оператор присваивания p = &x означает: "взять адресс переменной x и присвоить его значение переменной указателю p".

Пример:

 

int

var, *ptr_i, var;

double

ss, *ptr_d;

ptr_i = &var ; ptr_d = &ss ;

Определены два указателя:

*ptr_i – указатель на переменную типа int *ptr_d указатель на переменную типа double.

Указателю ptr_i присваивается адрес переменной var (говорят: ptr_i указывает на переменную var), а указателю ptr_d адрес переменной ss.

После того, как указатель установлен, можно обращаться к объекту, на который он указывает, для этой цели служит специальная операция "*".

6.3. Операция разыменования (*)

Унарная операция *, примененная к указателю, обеспечивает доступ к содержимому ячейки памяти, на которую ссылается указатель. Иными словами операция * рассматривает свой операнд как адрес и позволяет обратиться к содержимому этого адреса. Легко догадаться, что операндом операции * может выступать только указатель. Приведем различные названия операции *, используемые в литературе по программированию:

операцией разыменования (или разадресации);

операцией раскрытия ссылки;

косвенная адресация (или обращение по адресу).

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

На рис. 6.1. схематично изображен участок памяти, в которой располагаются две переменные указатель ptr_i и переменная var. Если указателю присвоен адрес переменной var, то операция разыменования, примененная к указателю, вернет значение переменной var.

Пусть указатель ptr_i имеет тип int, тогда комбинация *ptr_i эквивалентна произвольной переменной типа int. В этой связи важно заме-

Ук а зат ел ь

 

Адрес var

p tr _ i

 

 

 

 

 

 

 

 

 

 

 

 

 

.

 

 

.

 

 

.

 

 

 

Переменная

 

Содержимое

var

 

var

 

 

 

 

 

 

Рис. 6.1. Косвенный доступ к переменной var через указатель ptr_i

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

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

Пример:

 

int x, *ptr;

 

ptr = &x;

// ptr ссылается на x

*ptr= *ptr +1; // аналог: x = x+1

*ptr = *ptr*5;

// x=x*5

В первой строке определён указатель ptr на переменную int, а также и сама переменная x. Затем указатель устанавливается на переменную x, в дальнейшем он может использоваться в арифметических выражениях вместо переменной x.

PDF created with FinePrint pdfFactory Pro trial version http://www.fineprint.com

// нулевое значение указателя

6.4.Арифметика указателей

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

6.4.1. Операция присваивания

Операцию присваивания можно применять при занесении адреса или нулевого значения в указатель. Два указателя можно приравнять друг другу, в этом случае значение указателя правой части равенства заносится в левый указатель.

Пример:

int *p,*k,*z,date=2007; // установка указателя на переменную date p=&date; // значение указателя p заносится в указатель k k=p;

z=NULL;

6.4.2. Унарные операции изменения указателя, инкремент и декремент

(++ --)

При выполнении операций инкременат и декремента значение указателя увеличивается или уменьшается на длину типа, на который ссылается используемый указатель.

Если ptr некоторый указатель, то ptr++ увеличивает его значение на такую величину, которая обеспечивает адресацию следующего (соседнего) однотипного объекта. Следовательно, операции ++ и -- изменяют числовые значения указателей по-разному, в зависимости от типа данных с которыми связан указатель.

Изменение числовых значений указателя:

для типа char

+ (или – ) 1

для типа int

+ (или – ) 2

для типа float

+ (или – ) 4

для типа double

+ (или – ) 8

Пример: float *k; char *s;

\\+4(перемещение на следующее число) k++;

\\-1 (перемещение на предыдущий символ) s--;

6.4.3. Аддитивные операции (сложение и вычитание)

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

Пример: float *k,*i; int j;

PDF created with FinePrint pdfFactory Pro trial version http://www.fineprint.com

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]