Студопедия
Главная страница | Контакты | Случайная страница

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

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

Читайте также:
  1. RAID-массивы
  2. Адреса и указатели
  3. Адресный тип. Динамическая память. Адреса и указатели.
  4. Глава V Двумерные массивы
  5. Двумерные динамические массивы
  6. Двумерные массивы
  7. Двумерные массивы
  8. Двумерные массивы
  9. Двумерные массивы
  10. Двухмерные массивы

ГЛАВА 8. УКАЗАТЕЛИ И МАССИВЫ

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

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

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

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

· массивы указателей

· указатели на указатели

· массивы указателей и двумерные массивы

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

Одно из основных применений указателей – работа с массивами. В языке С++ указатели и массивы тесно связаны между собой. В С++ указатель, который ссылается на массив, можно индексировать так, как если бы это было имя массива.

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

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

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

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

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

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;

void fun (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]<<' '; // 2 4 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);

const int 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;

}

}




Дата добавления: 2015-01-29; просмотров: 180 | Поможем написать вашу работу | Нарушение авторских прав




lektsii.net - Лекции.Нет - 2014-2025 год. (0.02 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав