Указатели и одномерные массивы


Поскольку каждый элемент одномерного массива занимает в памяти компьютера одинаковое количество байтов, при этом, все элементы массива расположены подряд, это позволяет эффективно использовать указатели и арифметические операции при работе с ним.

При объявлении массива ему выделяется память, однако, после этого имя массива воспринимается как константный указатель того типа, к которому относятся элементы массива, и содержит адрес первого элемента (элемент с нулевым индексом) массива.

Имя массива является константным указателем на начало массива.

Применение операции адреса (&) к первому элементу массива даст адрес массива. Например, если объявлен массив

int mas[6];

то записи mas и &mas[0] эквивалентны и определяют адрес 1-го элемента массива, т.е. адрес самого массива. Оба значения являются константами типа указатель, их нельзя изменять на протяжении всей работы программы. Однако эти значения можно присваивать переменным типа указатель:

int mas[6];

int * p;

p = &mas[0]; // или p = mas; – указателю p

// присваивается адрес массива

Индекс элемента массива означает смещение элемента от начала массива на величину, равную

индекс * sizeof(тип)

байтов, где тип – тип элементов массива.

Используя операцию разыменования (*), действие операции индексирования ([]) можно объяснить так:

имя_массива[индекс] = *(имя_массива + индекс)

Поэтому, например, для массива masзаписи

mas[i] и *(mas + i) обозначают одну величину – значение соответствующего элемента массива, а записи

&mas[i] и (mas + i) обозначают один адрес элемента.

Индекс элемента массива определяет не его номер, а смещение относительно начала массива. Именно этим объясняется то, что индексы массивов начинаются с нуля.

Доступ к элементам массива

Если указателю присвоен адрес массива, то доступ к элементам массива можно осуществлять как с помощью индексирования имени массива, так и с помощью введенного указателя на начало массива. Если указатель p указывает на некоторый элемент массива, то p + 1 указывает на следующий элемент, p + i – на i-ый элемент после p, а p – i – на i-ый элемент перед p. Другими словами, если p указывает на mas[0], то:

(p+i) – адрес элемента mas[i]

*(p+i) – содержимое элемента mas[i]

Отсюда следует, что доступ к i-ому элементу одномерного массива mas, адрес начала которого хранится в указателеp,возможен следующими способами:

mas[i] *(mas + i) p[i] *(p + i)

При работе с массивами возможен любой из предлагаемых вариантов. Однако следует отметить, что компилятор преобразует все индексные выражения в адресные, т.е. встречая запись mas[i], компилятор преобразует её в *(mas+i), а запись p[i] – в *(p + i).

Указатель, который ссылается на массив, можно индексировать так, как если бы это было имя массива. Доступ к элементам массива возможен как с помощью индексов, так и с помощью указателей.

Несмотря на то, что объявления

int mas[6]; и int * p;

во многом схожи, они не являются полными аналогами.

Между именем массива и указателем, имеющим значение адрес массива, имеется существенное различие. Указатель – это переменная, содержащая некоторый адрес, поэтому можно использовать операторы:

int mas[] = {1, 2, 3, 4, 5};

int *p; p = mas;

int y = *p; // содержимое mas[0] присваивается y

*p++; p++;

(*p)++;

Выражение *p++ разыменовывает указатель *p и передвигает его к следующему элементу массива. Это возможно, поскольку известен тип адресуемых данных, а значит, и их размер. Выражение (*p)++ – разыменовывает указатель*pи к значению добавляет единицу.

А имя массива – это указатель-константа, поэтому следующие операторы не допускаются:

mas = p; mas++; *mas++;

Язык С++ позволяет программам разыменовывать имена массивов с помощью такого выражения, как *имя_массива:

int mas[5];

int x = *mas; // x = mas[0]

*mas = 77; // mas[0] = 77;

cout<<&mas<<" "<<&mas[0]; // вывод адреса массива mas

// Пример 8.1 Адресация элементов одномерного массива mas.

#include <iostream>

using namespace std;

const int n = 5;

int main(){

int mas[n]; // массив из n целых чисел

int * p = mas; // p– указатель на массив типа int

for(int i = 0; i < n; i++) // инициализация элементов массива,

mas[i] = i; // используя индекс

for(int i = 0; i < n; i++) // вывод массива, используя

cout<<*p++<<' '; // указатель p0 1 2 3 4

cout<<endl;

for(int i = 0; i < n; i++){

p = &mas[i];

cout<<*p<<' '; // 0 1 2 3 4

}

cout<<endl;

for(int i = 0; i < n; i++)

cout<<*(mas+i)<<' '; // 0 1 2 3 4

cout<<endl;

p = mas; *p = 5;

for(int i = 0; i < n; i++)

cout<<(*p)++<<' '; // 5 6 7 8 9

cout<<endl;

for(int * p = mas; p < mas + n; p++) // обнуление элементов

*p = 0; // массива mas – 0 0 0 0 0

system("pause");

}

Следует отметить, что нельзя выполнить оператор

int *q = &mas; // нельзя, т.к. типы не совпадают

но, выполнив операцию приведения типа, можно выполнить следующие операторы:

int *q = (int*)&mas; // можно, выполнили приведение типа

cout<<q<<endl; // можно, вывод адреса массива mas

Передача одномерных массивов в функцию

При передаче массива в функцию её параметр должен быть объявлен как указатель. Как раз это вариант чаще всего используется профессиональными программистами. В этом случае функция имеет следующий вид:

void vivod(int * num, int size){

for(int i = 0; i < size; i++)

cout<<num[i]<<' ';

cout<<endl;

}

Вызов функции в данном случае для массива mas[6]будет иметь следующий вид:

vivod(mas, 6);

В общем случае вызов функции имеет вид:

имя_функции (имя массива, размер массива);

Однако отдельный элемент массива, используемый в качестве аргумента функции, обрабатывается подобно обычной переменной.

Когда программа передаёт массив в функцию, C++ передаёт адрес памяти первого элемента этого массива. Используя переменную-указатель, функция может перемещаться по содержимому массива, просто увеличивая значение указателя.

Если массив используется в качестве аргумента функции, функции передаётсяадрес массива (адрес элемента массива с нулевым индексом).

Следует понимать, что, так как функция получает адрес массива, то она может изменить реальное содержимое массива, используемого при вызове функции. Покажем это на следующем примере.

// Пример 8.2. Функции fun() изменяет массив, используемый

// при вызове функции.

#include <iostream>

using namespace std;

const int DIM = 20;

voidfun(int * num, int size);

int main(){

int x[DIM], n;

cout<<"Vvedi n: "; cin>>n;

for(int i = 0; i < n; i++)

x[i] = i + 1;

for(int i = 0; i < n; i++)

cout<<x[i]<<' '; // 1 2 3 4 5

cout<<endl;

fun(x, n); // вызов функцииfun()

for(int i = 0; i < n; i++)

cout<<x[i]<<' '; // 24 6 8 10

cout<<endl;

system("pause");

}

void fun(int * num, int size){

for(int i = 0; i < size; i++)

num[i] = num[i] * 2; // или num[i]*= 2;

cout<<endl;

}

// Пример 8.3. Дан одномерный целочисленный массив. Поменять

// местами минимальный и максимальный элементы массива.

// Основные этапы решения задачи (ввод массива, вывод массива,

// обработка массива) оформить в виде функций.

#include <iostream>

using namespace std;

void init(int*, int);

void display(int*, int);

void obmen(int*, int);

constint DIM = 20;

int main(){

int a[DIM], n;

cout<<"Vvedi n: "; cin>>n;

init(a, n); // вызов init()

cout<<"\n\tIsxodni massiv\n"; display(a, n); // вызов display()

obmen(a, n); // вызов obmen()

cout<<"\n\tRezult massiv\n"; display(a, n); // вызовdisplay()

system("pause");

}

void init(int * a, int n){

srand(n);

int * p = a;

for(int i = 0; i < n ; i++)

p[i] = rand() % 20 - rand() % 10;

}

void display(int * a, int n){

for (int * p = a; p < a + n; p++)

cout<<*p<<' ';

cout<<endl;

}

void obmen (int * a, int n){

int imin = 0, imax = 0;

for(int i = 0; i < n ; i++){

if(*(a + i) < *(a + imin )) imin = i;

if(*(a + i) > *(a + imax )) imax = i;

}

int temp = a[imin]; a[imin] = a[imax];

a[imax] = temp;

}

// Пример 8.4. Дан одномерный массив целых чисел. Отсортировать

// массив по неубыванию. Массив и его размер ввести с клавиатуры.

// Основные этапы решения задачи оформить в виде функций.

#include <iostream>

using namespace std;

void init(int*, int);

void display(int*, int);

void sort (int*, int);

const int DIM = 50;

int main(){

int a[DIM], n;

cout<<"Vvedi n: "; cin>>n;

init(a, n);

cout<<"\n\tIsxodni massiv \n"; display(a, n);

sort(a, n);

cout<<"\n\tOtsortirrov. massiv\n"; display(a, n);

system("pause");

}

void init(int * p, int n){

srand(n);

for(int i = 0; i < n; i++)

p[i] = rand() % 20 - 10;

}

void display(int * p, int n){

for(int i = 0; i < n; i++)

cout<<p[i]<<' ';

cout<<endl;

}

void sort(int * p, int n){

for(int i =1; i < n ; i++)

for(int j = 0; j <n-i; j++)

if(p[j] > p[j+1]){

int x = p[j]; p[j] = p[j + 1]; p[j + 1] = x;

}

}



Дата добавления: 2022-05-27; просмотров: 66;


Поиск по сайту:

Воспользовавшись поиском можно найти нужную информацию на сайте.

Поделитесь с друзьями:

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.043 сек.