Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Оголошення вказівника, операції, пов’язані з вказівниками
Вказівник (покажчик, англ. pointer) – це особливий тип даних, значенням якого є адреса певного байта оперативної пам'яті. Найчастіше вказівник зберігає адресу першого байта одного з об’єктів програми. Це називається посиланням на вказаний об’єкт. Вказівники можуть бути константними і змінними: константні вказівники зберігають незмінну адресу оперативної пам'яті, зокрема константними вказівниками є імена масивів і символьних рядків; вказівники – змінні є змінними програми, їм можна надавати значення адрес різних ділянок оперативної пам'яті. Як і для змінних, вказівники необхідно оголошувати. Синтаксис оголошення змінних такий:
базовий_тип * ім’я_вказівника;
тут базовий тип – тип об’єктів програми, адреси яких може зберігати даний вказівник; це може бути довільний стандартний тип або тип користувача; * - ознака того, що наступна змінна є вказівником; ім’я вказівника – ідентифікатор. З вказівниками пов’язані дві унарні операції: & - визначення адреси, * - звертання до об’єкта за адресою. Значенням операції визначення адреси змінної є адреса операнда (тобто змінної), перед яким стоїть знак &. Розглянемо фрагмент програми:
#include <iostream> using namespace std; int main() { int a = 5, *pa; pa = &a; cout << pa << endl; }
тут змінна а – звичайна змінна цілого типу, ра – вказівник на ціле. В результаті виконання рядка pa = &a; змінна ра буде містити адресу першого байти пам'яті, яку займає змінна а. Значення адреси змінної можна присвоїти тим вказівникам, базовий тип яких збігається з типом змінної. Тобто, спроба компіляції наступної програми буде призводити до помилки:
#include <iostream> using namespace std; int main() { int a = 5, *pa; char c = 'z'; pa = &c; // Помилка, базовий тип вказівника і // тип змінної не співпадають }
Існують такі обмеження щодо застосування операції визначення адреси: не можна визначати адресу константи; не можна визначати адресу виразу; не можна визначати адресу змінної з класом пам'яті register. В оголошенні вказівника можна виконувати ініціалізацію значенням адреси об’єкта, що має відповідний до вказівника тип і був оголошений раніше. Наприклад:
int a = 5, *pa = &a;
Вказівники можна також ініціалізувати значеннями адрес – констант:
char *pc = (char *) 0x04cd;
Існує константа NULL, яку можна присвоювати вказівникам всіх типів. Вважається що вказівник, значенням якого є NULL, не посилається на жоден об’єкт програми. Такий вказівник називають порожнім вказівником. Операндом операції звертання за адресою є вказівник або адреса ділянки пам'яті, а результатом – значення об’єкта, який зберігається в цій ділянці. Цю операцію також називають розадресацією, вона є зворотною до операції взяття адреси. Результат цієї операції має тип, що був заданий як базовий в оголошенні вказівника. Звертання через вказівник можна використовувати всюди, де синтаксично може бути записаний об’єкт даного типу. Наприклад:
#include <iostream> using namespace std; int main() { int a = 5, *pa; pa = &a; // Отримали адресу змінної а *pa = 12; // Змінили значення змінної а cout << *pa << endl; cout << a << endl; }
В оголошеннях вказівників можна вказувати кваліфікатор const. Роль цього кваліфікатора визначається місцем його запису. Якщо кваліфікатор const в оголошенні передує базовому типу вказівника, то він означає, що за допомогою такого вказівника заборонено змінювати значення об’єкта, на який він посилається.
#include <iostream> using namespace std; int main() { int a = 5; const int b = 123; const int * cp; cp = &a; // Можна змінювати значення вказівника *cp = 12; // Помилка, не можна змінювати значення // об’єкта, на який посилається вказ-к cp = &b; cout << *cp << endl; // Можна читати значення об’єкта, на // який посилається вказівник }
Якщо кваліфікатор const в оголошенні передує імені вказівника, то такий вказівник буде константним. В оголошенні константний вказівник обов’язково необхідно проініціалізувати, змінювати це значення не можна.
#include <iostream> using namespace std; int main() { int a = 5, b = 12; int * const cp = &a; cp = &b; // Помилка, не можна змінювати значення // константного вказівника *cp = 12; // Можна змінювати значення об’єкта, на // який посилається вказівник cout << *cp << endl; // Можна читати значення об’єкта, на // який посилається вказівник
} Адресна арифметика Зручність використання вказівників пов’язана з можливістю виконання над ними таких операцій: присвоєння, порівняння, збільшення і зменшення, віднімання. Операції над вказівниками називають адресною арифметикою. Операції присвоєння, порівняння та віднімання бінарні, обидва операнди цих операцій обов’язково повинні бути вказівниками або адресними виразами з однаковим базовим типом. Операції збільшення чи зменшення значень вказівників можуть бути як унарними (постфіксний або префіксний інкремент або декремент вказівника) і бінарними – збільшення (зменшення) значення вказівника на задану цілочислову величину. Приклад використання операції присвоєння значень вказівників:
#include <iostream> using namespace std; int main() { int a = 5; int * p1, * p2; p1 = &a; p2 = p1; *p2 = 123; cout << a << endl; }
Над вказівниками (або адресними виразами) можна виконувати всі операції порівняння мови С++. Результатом виконання операції є величина логічного типу. Наприклад:
#include <iostream> using namespace std; int main() { int a = 5, b = 5; int * p1, * p2; p1 = &a; p2 = &b; if (p1 == p2) // Порівнюємо значення вказівників cout << "p1 == p2" << endl; else cout << "p1!= p2" << endl; if (*p1 > *p2) // Порівнюємо значення, на які // посилаються вказівники, тобто а і b cout << "a > b" << endl; else cout << "a <= b" << endl; }
До значення вказівника можна додавати (чи віднімати від нього) довільне ціле число. Результатом операції збільшення (зменшення) вказівника є нова адреса. Наприклад
#include <iostream> using namespace std; int main() { int a[ 5 ] = { 1, 2, 3, 4, 5 }; int * p; p = &a[ 0 ]; // Адреса першого елемента масиву cout << *p << endl; // Виводимо перший елемент масиву p++; // Адреса другого елемента масиву cout << *p << endl; // Виводимо другий елемент масиву }
У попередньому прикладі при виконанні операції p++ значення вказівника буде збільшуватися на sizeof(базовий_тип), тобто sizeof(int). Після виконання операції інкремента вказівник буде посилатися на наступне ціле значення в пам'яті, тобто на наступний елемент масиву. У загальному випадку, при збільшенні (зменшенні) значення вказівника на ціле число k фактично він буде змінюватися на k * sizeof(базовий_тип) і буде вказувати на інше значення базового типу в пам'яті. Таким чином, величина, яка додається до вказівника або віднімається нього завжди кратна розміру базового типу цього вказівника.
#include <iostream> using namespace std; int main() { int a[ 5 ] = { 1, 2, 3, 4, 5 }; int * p; p = &a[ 0 ]; // Адреса першого елемента масиву cout << *p << endl; // Виводимо перший елемент масиву p += 2; // Адреса третього елемента масиву cout << *p << endl; // Виводимо третій елемент масиву }
Операція віднімання виконується над двома вказівниками (або адресами), її результатом є кількість елементів базового типу, які можна розташувати в ділянці оперативної пам'яті, адреси початку і кінця якої задають вказівники. Наприклад
#include <iostream> using namespace std; int main() { int a[ 5 ] = { 1, 2, 3, 4, 5 }; int * p1, * p2; p1 = & a[ 0 ]; // Адреса першого елемента масиву p2 = & a[ 4 ]; // Адреса останнього елемента масиву cout << p2 - p1; // 4 елемента: 0-й, 1-й, 2-й, 3-й }
Операндом операції звертання за адресою може бути адреса ділянки пам'яті, в якій зберігається значення певного типу. Тип значення в пам'яті буде визначатися базовим типом вказівника. В наступній програмі спочатку обчислюється вираз в дужках, тобто знаходимо адресу четвертого елемента масиву, після цього звертаємося за цією адресою.
#include <iostream> using namespace std; int main() { int a[ 5 ] = { 1, 2, 3, 4, 5 }; int * p; p = & a[ 0 ]; // Адреса першого елемента масиву cout << *(p + 3); // Виводимо 4-й елемент масиву }
Всі інші операції, крім перелічених, виконувати над вказівниками не можна: не можна додавати чи множити вказівники, виконувати над ними побітові операції тощо.
|
||||||
Последнее изменение этой страницы: 2021-12-15; просмотров: 64; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.191.216.163 (0.015 с.) |