Указатели. Часть 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 вещественных чисел. Используя указатель нужно изменить значения элементов массива с индексами 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. Изменение значений элементов массива

Пример 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 указывает на строку массива с индексом 3
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]; // то же самое

// доступ к элементу массива с индексом [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


Связанные темы