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

Классы памяти. Массивы, операция индексации Цель работы

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

Методические указания

  1. Классы памяти

Каждая переменная, описанная в программе на языке Си, принадлежит к какому-либо классу памяти. Имеется четыре класса памяти и есть четыре ключевых слова, используемые для описания классов памяти: extern (для внешнего), auto (для автоматического), static (для статического) и register (для регистрового). Класс памяти переменной определяет время ее существования в оперативной памяти и область действия. Форма описания переменной с указанием класса памяти имеет такой вид:

[<класс>] <тип> <имя переменной> ;

    1. Автоматические переменные

Если при описании переменной отсутствует класс памяти, то по умолчанию она является автоматической. Область действия такой переменной – функция, в которой она описана. Память для таких переменных отводится динамически во время выполнения при входе в функцию (блок). При завершении работы функции автоматическая переменная исчезает, область памяти может использоваться для других целей.

    1. Внешние переменные

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

    1. Статические переменные

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

Внешние статические переменные определяются вне функции, также как и внешние (extern), однако в определении должно быть ключевое слово static. Разница между внешней переменной и внешней статической переменной заключается в области их действия. Обычная внешняя переменная может использоваться функциям в любом файле, в то время как внешняя статическая переменная может использоваться только в том файле, в котором она описана.

    1. Регистровые переменные

Регистровые (register) переменные хранятся в регистрах центрального процессора, где доступ к ним и работа с ними выполняются гораздо быстрее, чем в памяти. В этом случае регистровые переменные рассматриваются как автоматические. Использование регистровых переменных является скорее просьбой, чем обычным делом. Компилятор сравнивает эту просьбу с количеством доступных регистров. Если свободных регистров нет, то в этом случае переменная становится простой автоматической переменной.

  1. МАССИВЫ

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

    1. Одномерные массивы

Если в программе используется массив, то он должен быть описан. Форма описания массива имеет вид:

[<класс памяти] <тип> <имя> [<размер>];

Например, следующий фрагмент программы

static int Z[10];

float x [15], y [20]

Описывает статический массив целых чисел с именем Z из 10 элементов и два массива вещественных чисел с именами x и y размерами 15 и 20 соответственно. Элементы массива в памяти ЭВМ располагаются последовательно друг за другом и проиндексированы целыми положительными числами, называемыми индексами массива.

Индексирование массива в языке Си начинается от нуля, поэтому элементы массива Z из рассмотренного примера будут располагаться в память ЭВМ следующим образом: Z [0], Z [1],… Z [9]. Обращения к отдельной компоненте массива осуществляется указанием имени массива, за которым в квадратных скобках следует выражение, определяющее значение индекса. Например, запись Z [1] = 20; приводит к присвоению второму элементу массива Z значение 20.

    1. Инициализация массивов

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

Например int x [4] = {1, 2, 3, 4};

static float Z [3] = {1.2, 3, 5.4};

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

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

Пример:

static float S[] = {1.5, 3.5, 4};

Компилятор определит размер массива S равным трем. В программе размер массива можно определить выражением sizeof <имя массива> / sizeof (<тип>). Если внешние и статические массивы не инициализировать, то элементы массива принимают нулевое значение, автоматические и регистровые принимают произвольные значения. Ввод–вывод элементов массива выполняется поэлементно.

Рассмотрим примеры работы с одномерными массивами.

Пример 1.

В массиве из 50 элементов отыскать максимальный элемент.

/* программа */

# include <stdio:h>

# define RAS 50

void main ( )

{float max, a[RAS];

int i;

puts («вводите элементы массива \n»;

/* Цикл ввода элементов */

for (i = 0; i < RAS; scanf (“%f”, & a[i]), i ++);

/* Цикл определения max */

for (i = 1, max = a [0]; i <RAS; i ++)

if (a[i] > max) max = a[i];

printf (“max = % 5.2f \n”, max);

}

Пример 2. Сортировка элементов массива:

# include <stdio.h>

void main ( )

{static int a [ ] = {50, 20, 70,… 2};

int i, j, k, n, t;

/* определение размера массива */

n = sizeof A / sizeof (int);

/* сортировка методом выбора */

for (i = 0; i < n – 1; i ++)

{for (J = i + 1, k = i; j <n; j++)

if(a[j]<a[k] k = j;

t = a[k]; a[k] = a[i]; a[i] = k;

}

/* вывод массива по 5 элементов в строке */

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

printf (“a[%d] = % d % C ”, i, a[i], (i = = 5)? ‘\n’:’ ‘);

}

    1. Многомерные массивы

Если в описании массива размерность равна N ,то массив называется многомерным. В языке не накладывается ограничений на число измерений массива, однако на практике, как правило, используются двухмерные массивы. Приведем примеры описания многомерных массивов

static int x[5][4]; /*матрица размером 54*/

float Z[2][3][5]; /*трехмерный массив */

Элементы многомерных массивов располагаются в памяти ЭВМ последовательно друг за другом таким образом, что наиболее быстро меняется самый последний индекс, т.е. для массива x элементы будут расположены так:

x[a][0], x[0][1],…, x[0][3], x[1][0], x[1][1],…, x[4][3].

Для обращения к элементам многомерного массива используется та же конструкция, как и к одномерным массивам, за исключением того, что в каждой квадратной скобке указывается значение индекса по каждому измерению. Например, x[2][1] = 5 присваивает элементу, расположенному на пересечении третьей строки и второго столбца, значение 5.

Если массив – матрица, то при изменении второго индекса на единицу перемещаемся вдоль строки, а при изменении первого индекса на единицу – вдоль столбца. Для инициализации двухмерных массивов список инициализации может содержать разделительные фигурные скобки, например,

static int Z[3][2] = {{1, 2}, {4, 5}, {8, 9}}.

Данные, находящиеся в первых внутренних скобках присваиваются первой строке массива, данные во вторых внутренних скобках – второй и т. д. Если в какой–то последовательности число элементов будет меньше длины строки , то недостающим элементам присваивается ноль, если больше, то выдается сообщение об ошибке. Внутренние скобки можно опускать, в этом случае список инициализации рассматривается как линейная последовательность элементов в соответствии с их расположением в памяти, т. е. первые n элементов присваиваются первой строке массива, вторые n элементов – второй и т. д. Например

static int Z[3][2] = {1, 2, 3, 4}; /* Недостающие элементы инициализируются по умолчанию значением ноль */

  1. Пример выполнения задания

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

Организуем данные по количеству осадков в виде матрицы Z[10][12] так, что каждая строка матрицы будет содержать осадки по месяцам соответствующего года. Ниже приведен текст программы с пояснениями.

# include <stdio.h>

# define GOD 10

# define MES 12

void main ( )

{

int i, J;

float Summes, Sumqod; /* количество осадков за год и месяц*/

float Z[GOD][MES];

/* ввод элементов матрицы Z */

for (i = 0; i <GOD; i++)

for (J = 0; J<MES; J++)

{printf («вводите элемент Z[%d, %d] = ? \n”, i, J);

scanf (“% f”, & Z[i][J];

}

/* печать заголовка количества осадков по годам */

printf (“год количество осадков \n”);

/* циклы определения количества осадков за каждый год */

for (i = 0; i <GOD; i++)

for (J = 0, Sumqod = 0; J < MES; J++)

Sumqod+ = Z[i][J];

printf (“%5 d % 10.1f \n”, 1990+i, Sumqod);

}

/* печать заголовка количества осадков по месяцам */

printf (“ янв. фев. мар. апр. май. июн. июл. авг.”);

printf (“сен. окт. ноя. дек. \n”);

/* Циклы определения среднего количества осадков по месяцам*/

for (i = 0; i < MES; i++);

{

for (J = 0, Summes = 0; J < GOD; J++)

SUMMES+ = Z[J][i];

printf (“%4.1f”, SUMMES/GOD);

}

printf (“\n”);

}

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