
- •1 Основні відомості про вказівники
- •2. Вказівники та посилання
- •Void function_a (char*, int, short*);
- •Int *pi; /* вказівник-змінна на дані типу int */
- •3. Ініціалізація вказівника
- •4. Розіменування та присвоєння
- •5. Void-вказівник
- •6. Операція пересування вказівника
- •7. Використання вказівників з модифікатором const
- •8. Деактивації дії модифікатора
- •9. Подвійний вказівник
- •10. Вказівники і масиви
- •11. Доступ до ділянок динамічної пам'яті
- •12. Звільнення пам'яті
- •8. Операції з вказівниками
- •Int I, *pi; /* pi –змінна-вказівник */
- •13. Динамічні масиви
- •11. Посилання
- •Лабораторный практикум
- •Вопросы без ответов
- •3 Основні операції над вказівниками
- •4 Багаторівнева непряма адресація
- •5 Операції над вказівниками
- •Void main ()
- •Void main()
- •6 Проблеми, пов'язані з вказівниками
- •Int *х; /* змінній-покажчику 'х' виділена оп, але 'х' не містить значення адреси оп для змінної */
- •Int *х; /* х - ім'я покажчика, він одержав оп*/
- •Void main ()
- •9 Масиви
- •1.9.1 Основні поняття
- •Int а[5]; /* оголошення зовнішнього масиву */ main ()
- •9.2 Оголошення та звертання в одновимірних масивах
- •9.3 Оголошення та звертання до багатовимірних масивів
- •Int а[3][4]; /* а - вказівник-константа */
- •10 Масиви покажчиків
- •10.1 Робота з великими масивами
- •Void main()
- •Int *p[200], I, j; clrscr() ;
- •10.2 Вільні масиви та покажчики
- •11 Символьні рядки
- •11.1 Основні відомості про представлення рядків
- •11.2 Функції роботи з рядками
- •1. Функції введення рядків.
- •2. Функції виведення рядків.
- •14 Лекція №14
- •14.1 Вказівники Лекція № 2 - Вказівники та посилання
- •1.2.1. Вказівники
- •6. Вказівники і масиви
- •6.1. Вказівники і адреси
- •6.2. Вказівники і аргументи функцій
- •6.3. Вказівники і масиви
- •6.4. Адресна арифметика
- •6.5. Вказівники символів і функції
- •6.6. Вказівники – не цілі значення
- •6.7. Багатовимірні масиви
- •6.8. Масиви вказівників (вказівники на вказівники)
- •6.9. Ініціалізація масивів вказівників
- •6.10. Вказівники і багатовимірні масиви
- •6.11. Командний рядок аргументів
- •6.12. Вказівники на функції
- •Посібник для початківця про вказівники
- •6. Вказівники і структуровані програмні змінні
- •9. Вказівники типу far
- •10. Вказівники і динамічні змінні (керування пам'яттю)
- •9. Вказівники типу far
- •10. Вказівники і динамічні змінні (керування пам'яттю)
- •8. Вказівники і динамічні змінні (керування пам'яттю)
- •Void* operator new(size_t t)
- •Void operator delete(void* p)
- •Void main()
9. Подвійний вказівник
Інший спосіб деактивації дії модифікатора const це використаня операторів динамічної роботи з типами.
С++ дозволяє оголошувати вказівник на вказівник (подвійний вказівник). Загальний синтаксис має вигляд
тип** ім’я вказівника;
Операція подвійного знаходження адреси &&, яка інтуїтивно напрошується стосовно подвійного вказівника, є недопустимою, тобто наступний код є неправильним
int i = 1;
int **j = &&i; // недопустима операція
Розіменування подвійного вказівника до типованої зміної здійснюється через операцію **. Наведемо приклади
а) int i=5;
int* j=&i;
int** z=&j;
**z=4; // розіменування подвійного вказівника
Приклад 11
#include <windows.h>
#include <clocale>
#include <iostream>
void main()
{
setlocale (LC_CTYPE,"rus");
int i=5;
std::cout<< "Початкове значення i: "<< i<<std::endl;
int* j=&i;
int** z=&j;
**z=4; // розіменування подвійного вказівника
std::cout<< "Модифiковане значення i: "<<i<<std::endl;
system("pause");
}
Скомпілюйте наведений приклад.
б) int i;
int* j=&i;
int** z;
z=&j;
**z=4; // розіменування подвійного вказівника
Приклад 12
#include <windows.h>
#include <clocale>
#include <iostream>
void main()
{
setlocale (LC_CTYPE,"rus");
int i;
int* j=&i;
int** z;
z=&j;
**z=4; // розіменування подвійного вказівника
std::cout<< "Значення i: "<<i<<std::endl;
system("pause");
}
Скомпілюйте наведений приклад.
Зазначимо, що більше двох рівнів непрямої адресації, в переважній більості випадків не використовується. Проте різні компілятори дають різну кількість рівнів організації багаторівневих ланцюжків непрямої адресації. Так, наприклад Visual C++ 6.0 дозволяє організовувати до 1010 рівнів, а Turbo C++ - 70 рівнів.
10. Вказівники і масиви
В С++ ім'я масиву є адресою його першого елемента, тобто:
char ach[30]; // тут ach є адресою &ach[0];
Це робить простою організацію вказівників на масиви даних
int ach[10];
int* j;
// перший варіант організації вказівника j на масив achArray
j=&ach[0];
// другий варіант організації вказівника j на масив achArray
j=ach;
Наприклад у вас є вказівник на масив цілих чисел (int A[]). Вказівник спочатку буде вказувати на перше значення в масиві як показує наступний приклад:
Приклад 13
#include <windows.h>
#include <clocale>
#include <stdio.h>
void main()
{
setlocale (LC_CTYPE,"rus");
int A[3]={10, 20, 30};
int *p;
p = &A[0];
printf("p вказує на значення: %d\n", *p);
system("pause");
}
Скомпілюйте наведений приклад.
Приклад 14
#include <windows.h>
#include <clocale>
#include <stdio.h>
void main()
{
setlocale (LC_CTYPE,"rus");
int A[3]={10, 20, 30};
p = A;
printf("p вказує на значення: %d\n", *p);
system("pause");
}
Скомпілюйте наведений приклад.
Розглянемо організацію доступу до елементів масиву через вказівник. Цей процес складається з двох етапів:
1) ініціалізація вказівника адресою першого чи останнього елемента масиву;
2) використання циклічного оператора для доступу до елементів масива або маніпуляції адресою, яку містить вказівник. Зокрема, якщо j=&ach[0], то наступні звертання до і-го елемента масиву ach є рівносильними
ach[i] = j[i] = *(j+i);
Зауважимо: хоча операції * i & мають найвищий пріоритет, проте операція *j++ приведе до значення елемента масиву з індексом збільшеним на одиницю (читається даний вираз справа наліво). Тобто, при умові j=&ach[0]
*j++ = ach[1] = *(j+1) = *(j++).
Для того щоб перемістити вказівник до наступного елементу масиву, ми можемо написати p++. Ми також можемо, як деякі з вас могли вже здогадатися, нанисати p + 2, що перемістить вказівник відразу на 2 елементи. Потрібно бути обережним з верхньою межею масиву (в даному випадку це 3 елементи), тому що компілятор не може перевірити чи вийшли ви за межі масиву, використовуючи вказівники. Ви легко можете отримати повний збій системи якщо будете не акуратні. Ось ще один приклад. На цей раз він показує три значення які ми встановили:
Приклад 15
#include <windows.h>
#include <clocale>
#include <stdio.h>
void main()
{
setlocale (LC_CTYPE,"rus");
int A[3]={10, 20, 30};
int *p;
p = A;
for (int і=0;і<3;і++)
{
printf("p вказує на значення: %d\n", *p);
p++;
}
system("pause");
}
Скомпілюйте наведений приклад.
Для того щоб збільшити на одиницю значення елемента масиву, треба записати (*j)++.
Приклад 16
#include <windows.h>
#include <clocale>
#include <stdio.h>
void main()
{
setlocale (LC_CTYPE,"rus");
int A[3]={10, 20, 30};
int *p;
p = A;
for (int і=0;і<3;і++)
{
(*p)++;
printf("p вказує на значення: %d\n", *p);
p++;
}
system("pause");
}
Скомпілюйте наведений приклад.
Ми також можемо рухати вказівник в будь-яку сторону, так p - 2 це 2 елементи від того місця куди вказує вказівник. Переконайтесь, що ви збільшуєте та зменшуєте значення вказівника, а не значення змінної, на яку він вказує. Даний метод використання вказівників і масивів найбільш корисний при використанні циклів, таких як for чи while.
Відмітимо також , що якщо ми маємо вказівник на змінну, наприклад int* p, ми можемо розглядати його як масив. Наприклад, p[0] еквівалентне *p; а p[1] еквівалентне *(p + 1).
Доступ до матриці (двомірного масиву) організовується як масив вказівників на рядки, або як вказівник на вказівник, наприклад
Приклад 17
#include <windows.h>
#include <clocale>
#include <iostream>
#include <conio.h>
void main()
{
setlocale (LC_CTYPE,"rus");
const unsigned int row=10; //unsigned - невід'ємне значення
const unsigned int col=10;
float arfl[row][col]; //оголошення матриці
float* p1[row]; //оголошення масиву вказівників
float** p2=p1; //оголошення подвійного вказівника
int i,j; //оголошенні лічильників циклів
for (i=0; i<row; i++) //ініціалізація масиву елементів
{
for (j=0; j<col; j++)
arfl[i][j]=float(i+j); // матриці
p1[i]=&arfl[i][0]; // вказівників
}
float Suma=0,Suma_p1=0,Suma_p2=0;
for (i=0; i<row; i++) // обчислення суми елементів масиву
for (j=0; j<col; j++)
{
Suma+=arfl[i][j]; // через індентифікатор матриці
Suma_p1+=*(*(p1+i)+j);// через масив вказівників
Suma_p2+=*(*(p2+i)+j);// через подвійний вказівник
}
std::cout<<"Сума елементiв матрицi розрахована чеоез:"<<"\n";
std::cout<<" -iндентифiкатор масиву: "<<Suma<<"\n";
std::cout<<" - подвiйний вказiвник: "<<Suma_p2<<"\n";
std::cout<<" - масив вказiвникiв: "<<Suma_p1<<"\n";
system("pause");
}