Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
default-1.doc
Скачиваний:
23
Добавлен:
28.09.2019
Размер:
221.18 Кб
Скачать
  1. Массивы в Си.

Как известно, массив - это конечная совокупность данных одного типа. Можно говорить о массивах целых чисел, массивов символов и.т.д. Мы можем даже определить масссив, элементы которого - массивы( массив массивов), определяя, таким образм, многомерные массивы. Любой массив в программе должен быть описан: после имени массива добаляют квадратные скобки [], внутри которых обычно стоит число, показывающее количество элементов массива. Например, запись int x[10]; определяет x как массив из 10 целых чисел. В случае многомерных массивов показывают столько пар скобок , какова размерность массива, а число внутри скобок показывает размер массива по данному измерению. Например, описание двумерного массива выглядит так: int a[2][5];. Такое описание можно трактовать как матрицу из 2 строк и 5 столбцов. Для обрщения к некоторому элементу массива указывают его имя и индекс, заключенный в квадратные скобки(для многомерног массива - несколько индексов , заключенные в отдельные квадратные скобки): a[1][3], x[i] a[0][k+2]. Индексы массива в Си всегда начинаются с 0, а не с 1, т.е. описание int x[5]; порождает элементы x[0], x[1], x[2], x[3], x[4], x[5]. Индекс может быть не только целой константой или целой переменной, но и любым выражением целого типа. Переменная с индексами в программе используется наравне с простой переменной (например, в операторе присваивания, в функциях ввода- вывода). Начальные значения массивам в языке Си могут быть присвоены при компиляции только в том случае, если они объявлены с классом памяти extern или static, например:

static int a[6]={5,0,4,-17,49,1};

обеспечивает присвоения a[0]=5; a[1]=0; a[2]=4 ... a[5]=1. Как видите, для начального присвоения значений некоторому массиву надо в описании поместить справа от знака = список инициирующих значений, заключенные в фигурные скобки и разделенные запятыми. Двумерный массив можно инициировать так:

static int matr[2][5] = {{3,4,0,1,2},{6,5,1,4,9}};

Матрица хранится в памяти построчно, т.е. самый правый индекс в наборе индексов массива меняется наиболее быстро.

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

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

Например:

Одномерный массив семи вещественных чисел - инициализаторов: 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, обозначенный как float bonn[i] (где i=0, ..., 6), можно инициализировать так: float bonn[7]={1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7}; Это же самое можно записать, используя обычные операторы присвоения: bonn[0]=1.1; bonn[1]=2.2; bonn[2]=3.3; bonn[3]=4.4; bonn[4]=5.5; bonn[5]=6.6; bonn[7]=7.7. Этими спобобами Вы можете задавать начальные значения элементам массива, иначе говоря, так можно вводить массив в память компьютера в Си.

Двумерный массив целочисленных элементов - инициализаторов: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, обозначенный как int s[i][j] (где i=0, 2, ..., 3; j=0, 2, ..., 4), можно инициализировать как: int s[4][5]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}. По аналогии с первым случаем это соответствует набору следующих операторов присвоения:

int s[0][0]=1; int s[0][1]=2; int s[0][2]=3; int s[0][3]=4; int s[0][4]=5;

int s[1][0]=6; int s[1][1]=7; int s[1][2]=8; int s[1][3]=9; int s[1][4]=10;

int s[2][0]=11; int s[2][1]=12; int s[2][2]=13; int s[2][3]=14; int s[2][4]=15;

int s[3][0]=16; int s[3][1]=17; int s[3][2]=18; int s[3][3]=19; int s[3][4]=20;

Вообще многомерные массивы, в том числе и двумерные, можно инициализировать как массив массивов. Например, две следующие инициализации равны между собой:

int s[3][5]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; и

int s[3][5]={{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}};

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

Символьные массивы могут инициализироваться как обычный массив

Например: char srt[15]={'B', 'o', 'r', 'l', 'a', 'n', 'd', ' ', 'C', '+', '+'} или могут вводиться как строка символов char str[15]='Borland C++'

Отличие этих способов состоит в том, что во втором способе будет добавлен еще и нулевой байт. К тому же второй способ по количеству используемых символов значительно короче.

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

char str[80]='Уроки программирования на Си'. При инициализации массива без указания его размера Вы делаете это так:

char str[ ]='Уроки программирования на Си'. Компилятор Си сам определит необходимое количество элементов массива, включая и нулевой байт. Можно определять таким способом массивы любого типа, в том числе и многомерные массивы.

Например:

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

При объявлении массивов с неизвестным количеством элементов можно не указывать размер только в самых левых квадратных скобках:

int arr[][3]={1, 2, 3,

5, 6, 7,

8, 9, 0};

  1. Упорядочение в одномерных массивах.

  1. Адреса и указатели. Операции над указателями. Индексирование массива.

В языке C массивы и указатели тесно связаны друг с другом. Например, когда объявляется массив в виде int a[25], то при этом не только выделяется память для 25 элементов массива, но и формируется указатель с именем a, значение которого равно адресу первого по счету (нулевого) элемента массива. Доступ к элементам массива может осуществляться через указатель с именем a. С точки зрения синтаксиса языка указатель a является константой, значение которой можно использовать в выражениях, но изменить это значение нельзя.

Поскольку имя массива является указателем-константой, допустимо, например, такое присваивание:

int a[25];

int *ptr;

ptr=a;

В этом примере в переменную-указатель ptr записывается адрес начала массива a, т. е. адрес первого элемента массива.

Также справедливы следующие соотношения: например, имеется массив a[N], тогда истинными будут следующие сравнения:

a==&a[0];

*a==a[0].

Указатели можно увеличивать или уменьшать на целое число:

ptr=a+1;

Теперь указатель ptr будет указывать на второй элемент массива a, что эквивалентно &a[1].

При увеличении указателя на единицу адрес, который он представляет, увеличивается на размер объекта связанного с ним типа, например:

int a[25];

int *ptr=a;

ptr+=3;

Первоначально указатель ptr указывал на начало массива a. После прибавления к переменной ptr числа 3 значение указателя увеличилось на 3*sizeof(int), а указатель ptr теперь будет указывать на четвертый элемент массива a. Указатель можно индексировать точно так же, как и массив. На самом деле компилятор преобразует индексацию в арифметику указателей, например, ptr[3]=10 представляется как *(ptr+3)=10.

К указателям типа void арифметические операции применять нельзя, так как им не ставится в соответствие размер области памяти.

Таким образом, в языке C для доступа к элементам массива существует два различных способа. Первый способ связан с использованием обычных индексных выражений в квадратных скобках, например, a[7]=3 или a[i+2]=5. При таком способе доступа записываются два выражения, причем второе выражение заключается в квадратные скобки. Первое из этих выражений должно быть указателем, а второе – выражением целого типа. Указатель, используемый в индексном выражении, не обязательно должен быть константой, указывающей на какой-либо массив, это может быть и переменная-указатель. В частности, после выполнения присваивания ptr=a доступ к седьмому элементу массива можно получить как с помощью константы-указателя a в форме a[7], так и переменной-указателя ptr в форме ptr[7].

Второй способ доступа к элементам массива связан с использованием адресных выражений и операции косвенной адресации в форме *(a+3)=10 или *(a+i+2)=5.

При реализации на компьютере первый способ приводится ко второму, т. е. индексное выражение приводится к адресному. Для приведенных примеров обращение к элементу массива a[3] преобразуется в *(a+3).

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

*a=2;

a[0]=2;

*(a+0)=2;

*ptr=2;

ptr[0]=2;

*(ptr+0)=2;

присваивает начальному элементу массива значение 2.

Многомерные массивы в языке C – это массивы массивов, т. е. массивы, элементами которых, в свою очередь, являются массивы. При объявлении таких массивов в памяти компьютера создается несколько различных объектов. Например, при выполнении объявления двумерного массива int a2[4][3] в программе создается указатель a2, который определяет в памяти местоположение первого элемента массива и, кроме того, является указателем на массив из четырех указателей. Каждый из этих четырех указателей содержит адрес одномерного массива, представляющего собой строку двумерного массива и состоящего из трех элементов типа int, и позволяет обратиться к соответствующей строке массива.

Таким образом, объявление a2[4][3] порождает в программе три разных объекта: указатель с идентификатором a2, безымянный массив из четырех указателей и безымянный массив из двенадцати чисел типа int. Для доступа к безымянным массивам используются адресные выражения с указателем a2. Доступ к элементам массива указателей осуществляется с указанием одного индексного выражения в форме a2[2] или *(a2+2). Для доступа к элементам двумерного массива чисел типа int должны быть использованы два индексных выражения в форме a2[1][2] или эквивалентных ей *(*(a2+1)+2) и (*(a2+1))[2]. Следует учитывать, что с точки зрения синтаксиса языка C указатель a2 и указатели a2[0], a2[1], a2[2], a2[3] являются константами, и их значения нельзя изменять во время выполнения программы.

Размещение трехмерного массива происходит аналогично. Так, например, объявление float a3[3][4][5] порождает в программе, кроме самого трехмерного массива из 60 чисел типа float, массив из четырех указателей на тип float, массив из трех указателей на массив указателей на float и указатель на массив массивов указателей на float.

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

Например, обращение к элементу a2[1][2] можно осуществить при помощи указателя ptr2, объявленного в форме int *ptr2=a2[0], как обращение ptr2[1×3+2] (здесь 1 и 2 – это индексы используемого элемента, а 3 – число элементов в строке) или как ptr2[5]. Заметим, что внешне похожее обращение a2[6] выполнить невозможно, так как указателя с индексом 6 не существует.

Для обращения к элементу a3[2][3][4] из трехмерного массива тоже можно использовать указатель, описанный как float *ptr3=a3[0][0], с одним индексным выражением в форме ptr3[2×20+3×5+4] или ptr3[59].

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]