Язык программирования Си
Указатели
Указатели в языке Си объявляются при помощи символа "*":
int * pInt;
Здесь переменная pInt - это указатель на int или, проще, адрес переменной целого типа. Доступ к значению, хранящемуся по адресу указателя, производится через разыменование:
*pInt=6;
Забавно, что если написать обе строки (объявление указателя и присваивание) подряд, то получится синтаксически правильный фрагмент, но по смыслу он ошибочен. Объявлением указателя мы выделили память под сам указатель, т.е. под адрес некоторого объекта. Однако память под сам объект не выделена, и поэтому записывать значение 6 некуда.
При помощи оператора "&" можно получить адрес уже существующей переменной. Следующий пример демонстрирует, как можно установить указатель pint на переменную varlnt типа int:
int * pint; int varint; pint = &varInt;
После этого уже можно выполнять присваивание *plnt=6;. Теперь значение 6 попадет в память переменной varint.
Указатель, "не указывающий никуда", в языке Си называется Null. Это единственная неарифметическая константа. Иногда она представлена как NULL.
Сами по себе указатели не являются сложными типами с точки зрения обращения к ним. Их значением является адрес некоторого программного объекта. Как правило, они указывают на некоторый тип, который в свою очередь уже может иметь сложную составную структуру. Специфика работы с указателями заключается в том, что, например, префиксная или постфиксная операция ++ будет изменять значение указателя на 1, 2, 4 или некоторую другую величину в зависимости от длины (количеств байт, отведенных для представления) того типа, на который указывает этот указатель.
Еще одной и наиболее важной проблемой указателей является несогласованность времени жизни указателя (адреса объекта) и программного объекта, на который он указывает.
Например, функция сохраняет адрес некоторой своей локальной переменной в глобальном указателе. По выходу из функции памяти объекта уже нет. Она может быть перераспределена каким угодно образом, а адрес, где "все это" лежало до сих пор, существует и может быть использован для обращения.
Ошибки подобного рода очень трудно обнаружить, поскольку до некоторого времени поведение программы с дефектами такого вида может быть весьма правдоподобным. Это происходит до тех пор, пока "отданная" память никем не переопределялась, а потом такая программа "вдруг" перестает работать.
Строки
Для работы со строками в Си не введено специального типа, поэтому для представления элементов строки используется символьный тип. Принято, что строка - это массив символов (байт), заканчивающийся нулевым байтом ('\0'). Соответственно, пустая строка начинается именно с этого символа (байта с нулевым кодом).
Задать значение массиву символов простым присваиванием нельзя, необходимо пользоваться инициализацией, функциями ввода данных или функциями копирования. В разделе 3.5 рассмотрен пример подобной функции My_Strcpy. Следует помнить, что строковые константы в Си выделяются в двойных апострофах, а символьные, занимающие один байт, - в одиночных.
Объединения
Объединение описывает переменную, которая может иметь любой тип из некоторого множества типов, т.е. все они имеют собственные имена, но используют общую память.
Пример определения типа объединения:
union Big Word { long Bg long; char *Bg chart [4] ; }
А переменная X_Var такого типа определяется следующим образом:
union Dig Word X_Var;
Данные типа union Big_Word занимают память, необходимую для размещения наибольшего из своих элементов, и могут рассматриваться как аналог вариантной записи в языке Паскаль.
Константы
Константы в языке Си могут иметь одинаковые значения при различных формах своего представления. В особенности это относится к числовым значениям.
10, 012 и 0xA в языке Си будут соответствовать одному и тому же значению 10 или в двоичной форме 1010. Просто числовые константы, начинающиеся с цифры 0, считаются в Си заданными в восьмеричной форме представления, а с префиксом 0х - шестнадцатеричными.
Вещественные числа также можно записывать в различных формах 12.5, 1.2e1, 125e-1, где символ "е" или "Е" используется для отделения мантиссы числа от порядка. Предполагается, что вещественная константа всегда положительна, а предшествующий ей знак "минус", если указан, рассматривается как унарная операция смены знака.
Еще следует обратить внимание на символьные константы. Они записываются в одиночных кавычках: 'A', 'a', ' + ', '-' и т.п. В случае необходимости можно определить символ его кодом в таблице '\12' или '\xA', задавая после обратной наклонной черты номер символа в восьмеричной или шестнадцатеричной системе.
Ранее говорилось, что следует различать символы и строки символов, которые задаются двойными кавычками. Так, константе "A" будет соответствовать строка из двух символов: собственно 'A' и '\0', т.е. к байту символа будет добавлен второй байт с нулевым значением для представления признака конца строки.