Указатели. Описание указателей.



Мы поможем в написании ваших работ!


Мы поможем в написании ваших работ!



Мы поможем в написании ваших работ!


ЗНАЕТЕ ЛИ ВЫ?

Указатели. Описание указателей.



Указатели

Когда компилятор обрабатывает оператор определения переменной, он выделяет память в соответствии с типом (int) и инициализирует ее указанным значением. Все обращения в программе к переменной по ее имени (i) заменяются компилятором на адрес области памяти, в которой хранится значение переменной. Такие переменные называются указателями.

Итак, указатели предназначены для хранения адресов областей памяти. Есть три вида указателей – указатели на объект, на функцию и на void, отличающиеся свойствами и наоборот допустимых операций. Указатель не является самостоятельным типом, она всегда связан с каким-либо другим конкретным типом.

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

Тип (*имя) (список_типов_аргументов);

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

Тип *имя;

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

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

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

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

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

Инициализация указателей

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

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

Способы инициализации указателя:

1. Присваивание указателю адреса существующего объекта:

· С помощью операции получения адреса

· С помощью значения другого инициализированного указателя

· С помощью имени массива или функции которые трактуются как адрес

2. Присваивание указателю адреса области памяти в явном виде

3. Присваивание пустого значения

4. Выделение участка динамической памяти и присваивание ее адреса указателю.

Операции с указателями

С указателями можно выполнять следующие операции: разадресация, или косвенное обращение к объекту (*), присваивание, сложение с константой вычитание, инкремент (++), декремент (--), сравнение, приведение типов. При работе с указателями часто используется получение адреса (&).

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

При смешивании в выражении указателей разных типов явное преобразование типов требуется для всех указателей кроме void*. Указатель может неявно преобразовываться в значение типа bool, при этом ненулевой указатель преобразуется в true, а нулевой в false.

Присвоение без явного приведения типов допускается в двух случаях:

ü Указателям типа void*;

ü Если тип указателей справа и слева от операции присваивания один и тот же.

Таким образом, неявное преобразование выполняется только типу void*. Значение 0 неявно преобразуется к указателю на любой тип. Присваивание указателей на объекты указателям на функции (и наоборот) недопустимо. Запрещено и присваивать значения указателям-константам, впрочем, как и константам любого типа.

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

Инкремент перемещает указатель к следующему элементу массива, декремент – к предыдущему. Фактически значение указателя изменяется на величину sizeof(тип). Если указатель на определенный тип увеличивается или уменьшается на константу, его значение изменяется на величину этой константы, умножению на размер объекта данного типа.

Разность двух указателей – это разность их значений, деленная на размер типа в байтах. Суммирование двух указателей не допускается.

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

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

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

Арифметические операции. Приоритеты операций.

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

Инкремент перемещает указатель к следующему элементу массива, декремент – к предыдущему. Фактически значение указателя изменяется на величину sizeof(тип). Если указатель на определенный тип увеличивается или уменьшается на константу, его значение изменяется на величину этой константы, умножению на размер объекта данного типа.

Разность двух указателей – это разность их значений, деленная на размер типа в байтах. Суммирование двух указателей не допускается.

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

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

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

Арифметические операции

К арифметическим операциям относятся:

◆ сложение (+)

◆ вычитание (-)

◆ деление (/)

◆ умножение (*)

◆ остаток (%).

Все операции (за исключением остатка) определены для переменных типа int, char, float. Остаток не определен для переменных типа float.

Все арифметические операции с плавающей точкой производятся над операндами двойной точности.

Операции подчиняются следующ порядку выполнения:

1. Наивысший(++;--;-(унарный минус); *; /; %)

2. низший(+; -)

Опр-ры одного уровня старшинства вычисл-ся слева направо. Для изменения порядков можно исп-ть ().

 

Функции. Методы.

 

Функция – это именованная последовательность описаний и операторов, выполняющая какое-либо законченное действие. Функция может принимать параметры и возвращать значение.

Любая программа состоит из функций, одна из которых должна иметь имя main (с нее начинается выполнение программы). Функция начинает выполняться в момент вызова. Любая функция должна быть объявлена и определена. Как и для других величин, объявлений может быть несколько, а определение только одно. Объявление функции должно находиться в тексте раньше ее вызова для того, чтобы компилятор мог осуществить проверку правильности вызова.

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

[класс]тип имя ([список_параметров])[throw(исключения)]

{тело функции}

Рассмотрим составные части определения.

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

n Extern – глобальная видимость во всех модулях программы;

n Static – видимость только в пределах модуля, в котором определена функция.

q Тип возвращаемого функцией может быть любым, кроме массива и функции. Если функция не должна возвращать значение, указывается его тип void.

q Список параметров определяет величины, которые требуется передать в функцию при ее вызове. Элементы списка параметров разделяются запятыми. Для каждого параметра, передаваемого в функцию, указывается его тип и имя.

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

Функцию можно определить как встроенную с помощью модификатора inline, который рекомендует компилятору вместо обращения кс функции помещать ее код непосредственно в каждую точку вызова. Модификатор inline ставится перед типом функции. Он применяется для коротких функций, чтобы снизить накладные расходы на вызов. Директива inline рекомендательный характер и выполняется компилятором по мере возможности. Использование inline – функций можно увеличить объем исполняемой программы. Определение функции должно предшествовать ее вызовам, иначе вместо inline-расширения компилятор сгенерирует обычный вызов.

Тип возвращаемого значения и типы параметров совместно определяют тип функции.

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

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

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

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

Операторы цикла

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

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

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

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

Цикл завершается если условие его продолжения не выполняется. Возможно принудительное завершение как текущей итерации так и цикла в целом. Для этого служат операторы break, continue, return, goto. Передавать управление извне внутрь цикла не рекомендуется.

Цикл с предусловием (while)

Цикл с предусловием реализует структурную схему и имеет вид:

While (выражение) оператор

Выражение определяет условие повторения тела цикла представленного простым или составным оператором. Выполнение оператора начинается с вычисления выражения. Если оно истинно выполняется оператор цикла. Если при первой проверке выражение равно false цикл не выполнится ни разу. Тип выражения должно быть арифметическим или проводимым к нему. Выражение вычисляется перед каждой итерацией цикла.

Распространенный прием программирования – организация бесконечного цикла с заголовком while (true) либо while (1) и принудительным выходом из тела цикла по выполнению какого-либо условия.

В круглых скобках после ключевого слова while можно вводить описание переменной.



Последнее изменение этой страницы: 2016-08-15; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 35.170.64.36 (0.015 с.)