Арифметические действия с указателями.
К указателям применяются только две арифметические операции – сложение и вычитание.
Пример:
Пусть p1 – указатель на целое, содержащий значение 2000. Пусть целые имеют длину 2 байта после выражения p1++ содержимое p1 станет 2002, а не 2001. Каждый раз при увеличении p1 указатель будет указывать на следующее целое – это справедливо и для уменьшения. Каждый раз, когда указатель увеличивается, он указывает на следующий элемент базового типа, а когда уменьшается – на предыдущий элемент. В случаи указателей на символы это приводит к обычной арифметики. Все остальные указатели увеличиваются или уменьшаются на длину базового типа. Можно добавлять или вычитать из указателей целые числа.
Пример: p1=p1+9
Это выражение приводит к тому, что указатель p1 указывает на 9-й элемент по сравнению с элементом, на который он указывал до присвоения. Помимо добавления или вычитания указателей и целых чисел. Единственную операцию, которую можно выполнить с указателем, это вычитание одного указателя из другого. В большинстве случаев вычитание одного указателя из другого имеет смысл только тогда, когда оба указателя указывают на один объект, как правило, массив. В результате вычитания получается число элементов базового типа, находящихся между указателями. Кроме вышеуказанных не существует других арифметических операций применимых к указателям.
Нельзя умножать или делить указатели, нельзя складывать указатели, нельзя применять битовый сдвиг, нельзя добавлять или вычитать типы float, double.
Сравнение указателей.
Два указателя (одного типа) могут сравниваться друг с другом.
Пример: p1 = = p2
Результат операции будет истинно, если значение указателей p1 и p2 равны.
p1 ! = p2
Результат истинно, если значение p1 и p2 не равны. Аналогично > < =< =>. Обычно сравнение указателей используется, когда 2 или более указателей указывают на один объект.
Массивы указателей
Можно создавать массивы указателей. Указатели могут храниться в массиве так же, как и любые другие данные. Массивы указателей можно использовать для работы со всеми типами данных, но целесообразнее применять их для хранения символьных строк различного размера.
Определение char * s [5], требует от компилятора выделение в памяти места для 5 указателей, в каждый из которых должен содержать адрес символьного массива, причем каждый из массивов символов может иметь разное количество элементов. При этом строки могут разместиться в памяти ЭВМ так. Следует отметить, что обратиться к первой строке можно используя St [0] или * St. Обратиться к первому символу строки можно путем указателя * St[0]или St [0] [0], или * * St.
Пример:
static char * St [ ] =
{ "Москва"
"Минск"
"Ленинград "
};
Схема:
1000 1002 1003
St[0] | St[1] | St[2] |
1600 1606
М | О | С | К | В | А | \0 |
1607 1612
М | И | Н | С | К | \0 |
1613 1622
Л | Е | Н | И | Н | Г | Р | А | Д | \0 |
Для объявления массива целочисленных указателей 10-ти элементов.
Пример:
int * x[10];
Для присвоения адреса целочисленной переменной var третьему элементу массива следует написать x[2] = & var;
Для получения значения var следует написать * x[2]
Типичным использованием массивов указателей является хранение сообщений об ошибках.
Пример: Функция, выводящая сообщение об ошибках находится по полученному номеру.
void serror ( int num)
{ static char * err [ ] = {
" Нельзя открыть файл \ n ",
" Чтение ошибки \ n ",
" Запись ошибки \ n "
};
printf (" % S ", err [num]);
}
Здесь printf вызывается с указателем на символ, указывающим на одно из сообщений, номер которого передается в функцию.
Например, если num приняло значение 2, будет выдано сообщение "запись ошибки". Здесь static один из 4-х спецификаторов хранения поддерживаемых в С. Он говорит компилятору, как должны храниться переменные. Спецификаторы предшествуют объявлению переменных.
Формат: спецификатор_хранения тип имя_переменная;
Дата добавления: 2016-04-14; просмотров: 977;