Similar presentations:
Указатели (pointers)
1. Указатели (pointers)
1.2.
3.
4.
5.
6.
7.
Назначение указателей.
Объявление указателей.
Операции над указателями.
Указатели и массивы.
Указатели и строки.
Ссылки.
Указатели в параметрах функций.
1
2. Типы данных С++
Типбайт
Диапазон принимаемых значений
целочисленный (логический) тип данных
bool
1
0 / 255 (0 – false, 1-255 – true)
целочисленный (символьный) тип данных
char
1
0 / 255
целочисленные типы данных
short int
2
-32 768
unsigned short int
2
0 / 65 535
int
4
-2 147 483 648 / 2 147 483 647
unsigned int
4
0
long int
4
-2 147 483 648
unsigned long int
4
0
/
/
/
32 767
4 294 967 295
/
2 147 483 647
4 294 967 295
типы данных с плавающей точкой
float
4
-2 147 483 648.0 / 2 147 483 647.0
long float
8
-9 223 372 036 854 775 808 .0 / 9 223 372 036 854 775 807.0
double
8
-9 223 372 036 854 775 808 .0 / 9 223 372 036 854 775 807.0
2
3. 1. Назначение указателей
Оперативная память компьютера может рассматриваться как массив байтов,индексируемый от нуля. Номер каждого байта в этом массиве называется
его адресом.
Адресом переменной называется адрес ее первого байта места хранения.
Переменные, в которых хранятся адреса других переменных, называются
указателями.
Указатель – переменная, диапазон значений которой состоит из адресов
ячеек памяти или специального значения — нулевого адреса.
Последнее используется для указания того, что в данный момент указатель
не ссылается ни на одну из допустимых ячеек.
2 32
3
4. Назначение указателей (Тематика)
Обеспечивают гибкость программирования:указатель (рtr) знает лишь адрес переменной (а), сама переменная
может менять свое значение независимо от наличия указателя на нее.
а
ptr
Примеры:
1. Справочная служба 109.
Адрес – указатель, номер телефона – значение переменной.
Результат: при изменении номера нет необходимости оповещать об этом всех
абонентов.
2. Расчетный счет.
Счет не меняется, а содержимое – сколько угодно.
Результат: достаточно помнить номер счета или карты.
3. Файловый указатель.
Один и тот же указатель обращается всякий раз к текущему элементу файла,
после чего перемещается на следующий.
Результат: через один указатель можно работать с различными данными,
4
находящимися в файле
5. Назначение указателей (Техника)
Правильное понимание и использование указателей особеннонеобходимо для составления хороших программ по следующим
причинам:
•указатели являются средством, при помощи которого функции могут
изменять значения передаваемых в нее аргументов;
•при помощи указателей выполняется динамическое распределение
памяти;
•указатели позволяют повысить эффективность программирования;
•указатели обеспечивают поддержку динамических структур данных
(деревья, связные списки).
Однако указатель может вызвать и ряд затруднений:
•если указатель содержит неправильное значение, программа может быть
неработоспособной (access violation).
•можно легко ошибиться при использовании указателей;
•ошибки, связанные с неправильными значениями указателей, найти
очень трудно.
5
6. Объявление указателей
При объявлении переменной для нее резервируется память.При определении – этому участку памяти присваивается значение.
Общая форма объявления
указателя:
тип * имя;
int *р;
// р – указатель на int
int *р, q;
// q – не указатель
int *р, *q; // p и q – указатели
P = NULL; // пустой (нулевой) указатель
void* p;
// бестиповый указатель
Нулевой указатель − это указатель, хранящий специальное значение,
используемое для того, чтобы показать, что данная переменная-указатель
не ссылается (не указывает) ни на какой объект (в С и С++ - это 0 или
макрос NULL - нулевой адрес, зарезервирован ОС).
void используется для того, чтобы показать, что указатель означает просто
адрес памяти, независимо от типа величины, находящейся по этому адресу
6
7. Операции над указателями
1. Присваивание указателю значение адреса переменной (& - унарнаяоперация (амперсанд):
p=&q;
где p – указатель, q – идентификатор переменной,.
2. Определение значения, на которое ссылается указатель (* - унарная
операция косвенной адресации или разыменования):
val=*p; // в результате val=q
3. Увеличение (уменьшение) указателя: (+ сложение, ++ инкрементация, –
вычитание, –– декрементация).
Пример:
Если p1 – указатель, то р1++ перемещает указатель
на 1 байт, если *p1 имеет тип char;
4 байта, если *p1 имеет тип int ;
4 байта, если *p1 имеет тип float.
4. Разность двух указателей. Например, чтобы найти, на каком расстоянии
друг от друга находятся элементы массива.
7
8. Пример 2.1:
//Даны адреса переменных &a=63384,&b=64390,&c=64404.//Что будет выведено на печать?
# include <stdio.h>
int main()
{
float a,*p1;
int b,*p2;
char c,*p3;
a=2.5; b=3; c='A';
p1=&a; p2=&b; p3=&c;
p1++; p2++; p3++;
printf("\n p1=%u, p2=%u, p3=%u",p1,p2,p3);
return 0;
}
Ответ: р1=63388, р2=64394, р3=64405.
8
9. Правила присваивания указателей
1. Указатели одного типа можно сравнивать на равенство инеравенство.
2. Указатели разных типов несовместимы по присваиванию.
Приведение типов указателей
void *UndefPoint;
UndefPoint = 0xb8000000; // недопустимо
UndefPoint++;
// Для типа void * нет такой операции…
(int *)UndefPoint++;
// И так тоже ничего не получается…
((int *)UndefPoint)++;
// А так хорошо… Сколько скобок!
++(int *)UndefPoint;
// И вот так тоже хорошо…
9
10. Указатели и массивы
Указатель на массив – это адрес его первого элемента.Элементы массива расположены в памяти последовательно, поэтому
увеличение указателя на единицу означает смещение к следующему
элементу массива.
long array[100];
long sum = 0;
for (long* ptr = &array[0]; ptr < &array[99] + 1; ptr++)
sum += *ptr;
//или
for (long* ptr = array; ptr < &array[99] + 1; ptr++)
sum += *ptr;
Смешивать указатели и массивы можно, делать это не рекомендуется!
10
11. Указатели и строки
Строка в Си - это последовательность байт (букв, символов),завершающаяся в конце специальным признаком - байтом '\0'.
Указатель типа char* - это строка.
char *point[]={"понедельник","вторник",
"среда","четверг",
"пятница","суббота",
"воскресенье"};
int i,n;
n=sizeof(point)/sizeof(point[0]);
for(i=0;i < n;i++) {
printf("\n %s",point[i]); // 1)
printf("\n %p",point[i]); // 2)
}
1)
понедельник
вторник
среда
четверг
пятница
суббота
воскресенье
2)
00B8
00C4
00CC
00D2
00DA
00E2
00EA
Использование указателей, а не массивов с фиксированными размерами,
особенно целесообразно, когда предложения или слова должны быть разной
длины.
11
12. Указатели в параметрах функции
Изменить значение фактического параметра возможно с помощьюмеханизма указателей. С помощью указателя в вызываемую функцию
можно передать адрес любого объекта из вызывающей программы. Не
меняя самого параметра функции (адрес) можно изменить содержимое
1)
2)
ячейки по данному адресу
void main() {
positive(int *m);
int k=-3;
positive(&k);
printf("\n k=%d",k);
getch();}
void positive(int *m){
if (*m < 0)
*m=-*m;
}
Если в качестве параметра функции используется обозначение массива, то
на самом деле внутрь функции передаётся только адрес начала массива, а12
значит внутри функции можно изменять значения элементов такого массива.
13. Ссылки
int a;// переменная типа int
int &b = a; // ссылка на a
Ссылка - тот же указатель, т.е. если функции параметр передается как
ссылка, то функция работает не с копией параметра, а с самим
параметром.
void f(int &a)
{
a = 3;
}
void main()
{
int k = 4;
f(k);
printf("%d\n",k);
}
Программа выведет '3'. Если в объявлении 'f' убрать & перед a, то программа
выведет 4. Плюс ссылок - не надо пользоваться разыменовыванием
(оператор *) и взятием адреса (оператор &). Минус - обязательно надо
13
на что-нибудь ссылаться, то есть нельзя передать NULL как ссылку
14. Пример работы со ссылкой
Ссылка - псевдоним объекта, скрытая форма указателя, который прииспользовании автоматически разыменовывается.
int A = 10;
int &B = A;
cout << B << " ";
A /= 2;
cout << B << " ";
B *=5;
cout << A << " ";
int C = 20;
B = C;
cout << A << " ";
// B – ссылка на переменную A
// 10
// 5
// 25
// 20
Ссылка должна быть обязательно проинициализирована сразу при
объявлении.
Любое изменение значения ссылки повлечет за собой изменение того объекта,
14
на который данная ссылка указывает.