
Пример:
Int *kol, *num; Признаком указателя служит *.
double *lenght;
Операции над указателями: над указателями определены две унарные операции: & *
Унарная операция & возвращает адрес объекта в явном виде, поэтому оператор:
y = &x;
присваивает адрес x переменной y. Операцию & нельзя применять к константам и выражениям. Операция применима только к объектам, имеющим имя и размещенным в памяти.
Унарная операция * воспринимает свой операнд как адрес некоторого объекта и использует этот адрес для выборки содержимого. Поэтому, оператор:
z = *y;
присваивает z значение переменной, записанной по адресу y.
int *a; |
Объявляет переменную a типа «указатель на int», то есть содержащую адрес некоторого целого значения. |
&x |
Возвращает адрес переменной a |
*p |
Возвращает "переменную" по адресу, находящемуся в переменной p. |
Пример: int x, y, *px;
px=&x;
y=*px;
Это эквивалентно y = x;
Указатели могут встречаться в выражениях. Если y – указатель на целое ( int *y; ), то *y может появляться там же, где и любая другая переменная, не являющаяся указателем.
Пример:
*y = 7; //заносим 7 в ячейку памяти по адресу y
*x = *x*5; //увеличиваем значение по адресу x в 5 раз
(*z)++; //добавляем 1 к содержимому ячейки памяти с адресом z, круглые скобки обязательны
Вывод:
Тип данных |
Размер, байт |
Диапазон значений |
unsigned char |
1 |
0 … 255 |
signed char |
1 |
–128 … 128 |
unsigned short (int) |
2 |
0 … 65535 |
unsigned int |
2 |
0 … 65535 |
short int (short) |
2 |
–32768 … 32768 |
int |
2 |
–32768 … 32768 ( –215 … 215–1 ) |
unsigned long (int) |
4 |
0 … 4294967295 |
long (int) |
4 |
–2147483648 … 2147483648 ( –231 … 231–1 ) |
float |
4 |
| x | = 3.4E–38 … 3.4E+38 |
double |
8 |
| x | = 1.7E–308 … 1.7E+308 |
long double |
10 |
| x | = 3.4 E–4932 … 3.4E+4932 |
МАССИВЫ И СТРУКТУРЫ
К совокупностям данным относятся массивы, структуры и файлы
Массивы
МАССИВ – это множество переменных одного типа, характеризующихся одним именем. Как следует из их определения, массивы очень удобны, если приходится иметь дело с большими наборами однотипных данных.
-
описание массива
Формат: Синтаксис описания массива
<тип> <имя_переменной> [количество_элементов_массива]
-
Обращение (ссылка) к элементу массива
Отдельные элементы массива собственного имени не имеют. Доступ к ним можно получить, используя оператор [ ].
Формат:
<имя_массива>
[<индекс_элемента>]…
Данный оператор возвращает элемент массива, соответствующий индексу. Обратите внимание: индексация в Си начинается с 0, то есть правильными значениями индекса будут все значения в интервале
от 0 до <количество_элементов_массива>–1.
Все значения в квадратных скобках при определении массивов должны быть целыми постоянными выражениями. Пока будем считать, что они целые без знака.
Пример: page[5] line[i] screen[j][k] matr[i–1][j+i–1]
Массивы можно, как и остальные переменные, инициализировать сразу при их объявлении. При этом элементы массива перечисляются через запятую, и все вместе заключаются в фигурные скобки. Пример: int a[ 6 ] = { 1, 2, 3, 4, 5, 6 };
Количество элементов в списке может быть меньше формального количества элементов массива – при этом инициализируются первые n элементов массива, где n – количество элементов в списке инициализации. С другой стороны, если указаны все элементы массива, то формальное количество элементов может отсутствовать:
int a[ ] = { 1, 2, 3}).
Теперь вопрос: что напечатает такая программа?
#include <stdio.h>
void main (void)
{ int i, a[10];
a[0] = 5;
printf ( "%d\n", *a ); }
На первый взгляд кажется, что она даже не будет компилироваться – ведь мы пытаемся взять значение по переменной, не являющейся адресом. Но, вопреки ожиданиям, она запустится и напечатает число 5.
Как вы можете догадаться из этого, имя массива в Си является указателем на его первый элемент. Запомните это раз и навсегда – это очень важно.
Теперь можно рассказать о операциях над указателями более подробно. Пусть у нас есть переменная int *a, и мы пишем a += 3. Что получится? Можно подумать, что теперь значение a сместится на 3 байта относительно своего текущего положения. Однако это не так – компилятор автоматически внесет поправку на размер int. То есть, a+3 будет указывать на третий элемент воображаемого массива, который начинается в памяти там, куда указывает a. Другими словами, a+3 и &(a [3]) эквивалентны.
А так как, например, у меня размер переменной типа int составляет 4 байта, то значение переменной сместится на 12 байт.
Таким же образом производится и вычитание из указателя целого числа. Но, учитывая, что элементов массива с отрицательным индексом не существует (реальное поведение программы всегда зависит от компилятора, но стоит придерживаться стандарта), правильнее сказать так: a–3 указывает на начало массива, третий элемент которого расположен там, куда указывает a. И, наконец, если даны int *a и int *b, то a–b имеет тип int и показывает, какой номер в массиве, расположенный там, куда указывает a, имеет элемент, расположенный там, куда указывает b. Здесь, в отличие от остальных случаев, результат может быть и отрицательным. Вычитать разнотипные указатели нельзя.
Строки
Язык СИ не поддерживает отдельный строковый тип данных, но он позволяет определить строки двумя различными способами.
В первом используется массив символов, а во втором – указатель на первый символ массива. Объявление char а[10] указывает компилятору на необходимость резервирования места для максимум на 10 символов. Константа а содержит адрес ячейки памяти, в которой помещено значение первого объекта типа char.
Второй способ определения строки – это использование указателя на символ. Объявление char *b; задает переменную b, которая может содержать адрес некоторого объекта. Однако в данном случае компилятор не резервирует место для хранения символов и не инициализирует переменную b конкретным значением. Когда компилятор встречает инструкцию вида b=”Москва”; , он производит следующие действия. Во-первых, как и в предыдущем случае, он создает в каком-либо месте объектного модуля строку Москва, за которой следует нулевой символ. Во-вторых, он присваивает значение начального адреса этой строки (адрес символа М) переменной b.
Константа (литерал) типа строка (string): " <текст> "