Покажчики. Частина 3. Некеровані покажчики і масиви. Покажчик на структуру. Покажчик на клас

Покажчики. Частина 3. Некеровані покажчики і масиви. Покажчик на структуру. Покажчик на клас

Ця тема базується на темі: “Покажчики. Керовані та некеровані покажчики”.


Зміст


1. Як описати некерований покажчик (*) на масив цілих чисел? Приклад

Щоб налаштувати покажчик на масив, потрібно присвоїти покажчику адресу першого елементу масиву.
Також можна, за бажанням, присвоїти покажчику адресу i-го елементу масиву.

Нехай дано масив цілих чисел і покажчик на тип int:

// Налаштування покажчика на масив цілих чисел
int M[20]; // Масив M з 20 цілих чисел
int *p;    // покажчик на тип int, значення p невизначене

Щоб налаштувати покажчик на перший елемент масиву є 2 способи:

// спосіб №1
p = &M[0]; // покажчик p вказує на 1-й елемент масиву

// спосіб №2
p = M; // так само як у способі №1

2. Як описати некерований покажчик (*) на масив дійсних чисел?

Для дійсних чисел налаштування покажчика на масив здійснюється так само як для цілих чисел:

// Налаштування покажчика на масив дійсних чисел
float X[20]; // Масив X з 20 дійсних чисел
float *p;    // покажчик на тип float, значення p невизначене

// спосіб №1
p = &X[0];   // покажчик p вказує на 1-й елемент масиву

// спосіб №2
p = X; // так само як у способі №1

// доступ до елементу масиву через покажчик
*p = -4.5f; // X[0] = -4.5

3. Способи присвоєння некерованому покажчику (*) значення адреси деякого елементу масиву. Приклад

Приклад 1. Способи присвоєння покажчику адреси першого елементу одновимірного масиву.

// доступ до елементів масиву через покажчик
int A[20]; // масив
int * p;   // покажчик

// спосіб 1
p = A;     // покажчик p вказує на масив A

// спосіб 2
p = &A[0]; // покажчик p вказує на масив A

Приклад 2. Способи присвоєння покажчику адреси i-го елементу одновимірного масиву.

// доступ до елементів масиву через покажчик
int A[20]; // масив
int * p;   // покажчик
int i;

i = 3;

// спосіб 1
p = &A[i]; // покажчик p вказує i-й елемент масиву A

// спосіб 2
p = A+i; //

4. Як доступитись до елементів масиву з допомогою некерованого (*) покажчика? Приклади

Приклад 1. Нехай дано масив A з 10 дійсних чисел і покажчик p. Змінити значення елементів масиву з індексами 0, 2, 7 через покажчик.

// одновимірний масив і покажчик
float A[10]; // масив з 10 дійсних чисел
float *p;    // покажчик на float

p = &A[0];   // p вказує на A

*p = 13.6;      // A[0] = 13.6
*(p+2) = 50.25; // A[2] = 50.25
*(p+7) = -3.2;  // A[7] = -3.2

Рисунок 1 демонструє результат вищенаведеного прикладу.

C++ покажчик масив зміна
Рисунок 1. Результат роботи прикладу 1

Приклад 2. Занулення масиву цілих чисел з допомогою покажчика на цей масив.

// доступ до елементів масиву через покажчик
int A[20]; // масив
int * p;   // покажчик
int i;

for (i=0; i<20; i++)
 A[i] = i;

p = A; // p вказує на масив A

// спосіб 1
for (i=0; i<20; i++)
 *(p+i) = 0;

// спосіб 2
for (i=0; i<20; i++)
 *(A+i) = 0; // ім'я масиву є теж покажчиком

// спосіб 3
for (i=0; i<20; i++)
 p[i] = 0;

5. Як здійснити доступ до елементів двовимірного масиву через покажчик? Приклади

Щоб покажчик вказував на двовимірний масив, потрібно покажчику присвоїти значення першого елементу двовимірного масиву. Для цього існує декілька способів.
Щоб покажчик вказував на рядок масиву, потрібно цьому покажчику присвоїти адресу цього рядка.



Приклад 1. Нехай дано двовимірний масив M цілих чисел і покажчик p. Реалізувати доступ до елементів масиву M через покажчик.

// Покажчик на двовимірний масив
int M[6][9]; // Двовимірний масив M цілих чисел
int *p1, *p2, *p3; // покажчики на тип int
 
p1 = (int *)M; // p1 = &M[0], p1 вказує на рядок з індексом 0
p2 = (int *)M[2]; // p2 вказує на рядок масиву з номером 2
p3 = (int *)&M[5]; // p3 вказує на рядок масиву з номером 5

// доступ до конкретного елементу масиву через покажчик
*p1 = 39;  // M[0][0] = 39
*p2 = 88;  // M[2][0] = 88
*p3 = 100; // M[5][0] = 100

*(p1+3) = 27;  // M[0][3] = 27
*(p2+5) = -13; // M[2][5] = -13
*(p3+8) = 19;  // M[5][8] = 19

Рисунок 2 демонструє результат роботи вищенаведеного коду.

C++ покажчик двовимірний масив

Рисунок 2. Доступ до елементів двовимірного масиву через покажчик

Приклад 2. Дано двовимірний масив дійсних чисел розміром 3×4. З допомогою покажчика отримати доступ до елементу масиву, що знаходиться в позиції 2, 3.

// покажчик на конкретний елемент
double B[3][4]; // масив
double * pb;    // покажчик на double

pb = &B[2][3];  // pb вказує на елемент масиву B з індексом (2,3)
*pb = 8.55;     // B[2][3] = 8.55

6. Доступ до елементів багатовимірного масиву через покажчик. Приклади

Приклад. Опис покажчика на трьохвимірний масив розміром 2×3×5. Доступ до елементу масиву з допомогою покажчика.

// покажчик на трьохвимірний масив
float A[2][3][5]; // трьохвимірний масив
float *p;        // покажчик на float

p = (float *)A;  // p вказує на перший елемент масиву
p = &A[0][0][0]; // p вказує на перший елемент масиву

// доступ до елементу масиву з індексом [2][0][3]
p = &A[2][0][3]; 
*p = -30; // A[2][0][3] = -30

7. Як описати некерований (*) покажчик на структуру? Приклад опису та використання некерованого покажчика на структуру

Приклад 1. Нехай за межами класу описується новий тип – структура ARRAY_INTS:

typedef struct Array_Ints
{
 int n;
 int A[20];
} ARRAY_INTS;

Тоді, в деякому методі класу (наприклад, обробнику події кліку на кнопці) можна використовувати структуру

ARRAY_INTS AI;    // структурна змінна AI
ARRAY_INTS * pAI; // покажчик на структуру

pAI = &AI; // pAI вказує на структуру типу ARRAY_INTS

// доступ до елементів структури через змінну AI
AI.n = 2;
AI.A[0] = 25;
AI.A[1] = 33;

// доступ до елементів структури AI через покажчик pAI
pAI->n = 3;      // AI.n = 3
pAI->A[0] = 28;  // AI.A[0] = 28
pAI->A[1] = 345; // AI.A[1] = 345
pAI->A[2] = -33; // AI.A[2] = -33

Приклад 2. Виділення пам’яті під структуру типу ARRAY_INTS (див. попередній приклад) і доступ до полів структури через покажчик:

// Приклад виділення пам'яті для покажчика на структуру
ARRAY_INTS * pAI2; // опис покажчика на структуру типу ARRAY_INTS

pAI2 = (ARRAY_INTS *)malloc(sizeof(ARRAY_INTS)); // виділення пам'яті

// заповнення полів
pAI2->n = 2;
pAI2->A[0] = 82;
pAI2->A[1] = 34;

8. Як описати некерований (*) покажчик на клас? Приклад

Нехай у модулі “MyClass.h” дано опис:

// опис класу в модулі "MyClass.h"
class MyClass
{
    private:
        int x; // поля класу
        int y;
    public:
        // методи класу
        void SetXY(int nx, int ny);
        int GetX(void);
        int GetY(void);
        MyClass(void);
};

У модулі “MyClass.cpp” дано реалізацію методів класу:

// реалізація методів класу в модулі "MyClass.cpp"
#include "StdAfx.h"
#include "MyClass.h"

MyClass::MyClass(void)
{
    x = 0;
    y = 0;
}

void MyClass::SetXY(int nx, int ny)
{
    x = nx;
    y = ny;
}

int MyClass::GetX(void)
{
    return x;
}

int MyClass::GetY(void)
{
 return y;
}

Щоб отримати доступ до полів та методів класу через покажчик можна написати такий код:

// Доступ до методів та полів класу через покажчик
MyClass * p; // покажчик на клас

// виділення пам'яті для покажчика 
p = (MyClass *)malloc(sizeof(MyClass));

// доступ до методів класу через покажчик
p->SetXY(5, 6); // виклик методу SetXY() класу

int x = p->GetX(); // x = 5
int y;
y = p->GetY(); // y = 6

9. Приклад опису керованого покажчика (^) на клас

У Visual C++ , якщо додаток створений для виконання в середовищі CLR, можна описувати керований покажчик на клас. У цьому випадку клас має бути оголошений з кваліфікатором ref. Виділення пам’яті для покажчика реалізується утилітою gcnew.

Приклад. Нехай дано клас, який описаний в модулі “MyClass2.h“.

ref class MyClass2
{
    private:
        int x;
        int y;

    public:
        void SetXY(int nx, int ny);
        int GetX(void);
        int GetY(void);
        MyClass2(void);
};

Реалізація методів класу в модулі “MyClass2.cpp” має вигляд:

#include "StdAfx.h"
#include "MyClass2.h"

MyClass2::MyClass2(void)
{
    x = 0;
    y = 0;
}

void MyClass2::SetXY(int nx, int ny)
{
    x = nx;
    y = ny;
}

int MyClass2::GetX(void)
{
    return x;
}

int MyClass2::GetY(void)
{
    return y;
}

Тоді можна використовувати керований покажчик на клас наступним чином:

// Приклад доступу до класу з допомогою керованого покажчика
MyClass2 ^ p; // керований покажчик на клас
int x, y;

p = gcnew MyClass2; // виділення пам'яті для покажчика

p->SetXY(-8, 32); // виклик методу SetXY() через покажчик p
 
x = p->GetX(); // x = -8
y = p->GetY(); // y = 32


Зв’язані теми