Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
приблудова рулит.doc
Скачиваний:
38
Добавлен:
27.09.2019
Размер:
403.46 Кб
Скачать

14 Операции над указателями

Над указателями определено 5 основных операций.

     Определение адреса указателя: &p, где p – указатель (&p – адрес ячейки, в которой находится указатель).

     Присваивание. Указателю можно присвоить адрес переменной p=&q, где p – указатель, q – идентификатор переменной.

     Определение значения, на которое ссылается указатель: *p (операция косвенной адресации).

     Увеличение (уменьшение) указателя. Увеличение выполняется как с помощью операции сложения (+), так и с помощью операции инкремента (++). Уменьшение – с помощью операции вычитания (–) либо декремента (––).

Например, пусть p1 – указатель, тогда р1++ перемещает указатель на:

o    1 байт, если *p1 имеет тип char;

o    4 байта, если *p1 имеет тип int (в 32 разрядной операционной системе) или 2 байта (в 16 разрядной операционной системе);

o    4 байта, если *p1 имеет тип float.

       Разность двух указателей. Пусть р1 и р2 – указатели одного и того же типа. Можно определить разность р1 и р2, чтобы найти, на каком расстоянии друг от друга находятся элементы массива.

Пример программы.

Даны адреса переменных &a=63384,&b=64390,&c=64404. Что напечатает ЭВМ?

# include <stdio.h>

int main()

{

float a,*p1;

int b,*p2;

char c,*p3;

a=2.5; b=3; c='A';

p1=&a; p2=&b; p3=&c;

p1++; p2++; p3++;

printf("\n p1=%u, p2=%u, p3=%u",p1,p2,p3);

return 0;

}

Ответ: р1=63388, р2=64392, р3=64405.

15 Массивы указателей

Указатели и массивы

Массив – это набор пронумерованных однотипных данных.

Синтаксис определения массива:

спецификатор_типа array[константное_выражение];

В определении массива array – имя массива, константное_выражение – ко-

личество элементов в массиве, спецификатор_типа – тип элементов в масси-

ве. Все элементы массива пронумерованы, начиная с нуля.

При определении массива его элементы можно инициализировать сле-

дующим образом:

спецификатор_типа array[ ]={ значение1,значение2, …, значениеN };

В фигурных скобках { } через запятую перечисляются значения элемен-

тов массива соответствующего типа.

В языке СИ между указателями и массивами существует некоторая связь.

Когда объявляется массив, то его имя отождествляется с константой, значение

которой равно адресу нулевого элемента массива.

Пример определения и использования массива.

int array[5]={2, 8, 45, 16, 12}; /* Определение и инициализация массива */

int *ptr; /* Определение указателя */

ptr=&array[0]; /* Присваивание адреса нулевого элемента массива

указателю ptr */

Указатель ptr устанавливается на адрес нулевого элемента масcива, при-

чем присваивание ptr=&array[0] можно записать в эквивалентной форме

ptr=array.

Между именем массива и указателем, выступающим в роли имени масси-

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

тима операция изменения ее значения: ptr=array или ptr++. Но имя массива не

является переменной, и записи типа array =ptr или array++ ошибочны.

Многомерные массивы так же часто используются, как и одномерные. Вот примеры: в школьных журналах написаны Фамилия и класс; любые базы данных; Вообще, многомерные массивы - это массивы массивов. Т.е. каждый индексный номер содержит массив. Вот пример уже из языка Си:

int i[2][4] = {{1,2,3,4}, {5,6,7,8}};

Т.е. тут мы создаем двумерный массив размером 2х4. Т.е. 2 строчки по 4 элемента каждая. В принципе, остальное тут так же. Давайте теперь рассмотрим, как в многомерном массиве вводить и выводить элементы:

#include <conio.h> #include <stdio.h> int main() {     int arr[2][4];     for (int i = 0; i < 2; i++){        for (int j = 0; j < 4;j++ ){           scanf ("%d", &arr[i][j]);        }     }     for (int i = 0; i < 2; i++){        for (int j = 0; j < 4;j++ ){           printf ("%d ", arr[i][j]);        }        printf ("\n");     }     getch(); return 0; }

Все очень похоже на одномерный массив. Только в многомерном массиве мы создаем двойной цикл, первый - это проход по столбцу, а второй - это проход по элементам массива (идем по строке). Во всех моих примерах при изменении размера многомерного массива, например вместо arr[2][4], хочу сделать arr[7][6]. Так вот, что бы сделать такое изменения придется изменять абсолютно все циклы, так как они ориентируются по старым данным. Но есть способ исправить эту проблему. Для этого в языке С/C++ есть директива предпроцессора define. Давайте рассмотрим его на примере:

#include <conio.h> #include <stdio.h> #define SIZE_A 2 #define SIZE_B 2 int main() {     int arr[SIZE_A][SIZE_B];     for (int i = 0; i < SIZE_A; i++){        for (int j = 0; j < SIZE_B;j++ ){           scanf ("%d", &arr[i][j]);        }     }     for (int i = 0; i < SIZE_A; i++){        for (int j = 0; j < SIZE_B;j++ ){           printf ("%d ", arr[i][j]);        }        printf ("\n");     }     getch(); return 0; }

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

void printArr (int arr[][2]){ //тело; }

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

printArr(arr);

Вот и все, что хотелось вам рассказать о многомерных массивах. Лучше всего любой материал по программированию запоминается на практике.