
- •Форматный ввод/вывод данных.
- •1.Форматный вывод
- •2.Форматный ввод .
- •Операции языка с.
- •Лабораторная работа №1 Данные. Типы данных. Приведение типов. Циклы Теоретическая часть Типы данных
- •Оператор sizeof
- •Преобразования типов.
- •Примеры программ
- •Задание на лабораторную работу № 1
- •Операторы организации условных и безусловных переходов.
- •If (проверка_условия) инструкция_1; else инструкция_2;
- •Примеры программ
- •Задание на лабораторную работу № 2
- •Массивы.
- •Строки символов.
- •Структуры.
- •Оператор typedef.
- •Битовые поля.
- •Смеси (объединения).
- •Перечисляемый тип данных.
- •Примеры программ
- •Задание на лабораторную работу № 3
- •Примеры программ
- •Классы памяти.
- •Указатели на функции.
- •Рекурсия.
- •Примеры программ
- •Задание на лабораторную работу № 5
- •Контрольные вопросы:
- •Рекомендуемая литература
Массивы.
В программе на языке С можно использовать структурированные типы данных. К ним будем относить массивы, структуры и файлы.
Массив состоит из многих элементов одного и того же типа. Ко всему массиву целиком можно обращаться по имени. Кроме того, можно выбирать любой элемент массива. Для этого необходимо задать индекс, который указывает его относительную позицию. Число элементов массива назначается при его объявлении и в дальнейшем не меняется. Если массив объявлен, то к любому его элементу можно обратиться следующим образом: указать имя массива и индекс элемента в квадратных скобках. Массивы объявляются так же, как и переменные:
int a[100];
char b[30];
float с[42];
В первой строке объявлен массив а из 100 элементов целого типа: а[0],а[1],...,а[99].(индексация всегда начинается с нуля). Во второй строке элементы массива b имеют тип char, а в третьей - float.
Двумерный массив представляется как одномерный, элементы которого тоже массивы. Например, объявление char a[10][20]; задает такой массив. По аналогии можно установить и большее число измерений. Элементы двумерного массива хранятся по строкам, т. е. если проходить по ним в порядке их расположения в памяти, то быстрее всего изменяется самый правый индекс. Например, обращение к девятому элементу пятой строки запишется так: а[5][9]. Пусть задано объявление:
int а[2][3];
Тогда элементы массива а будут размещаться в памяти следующим образом: а[0][0],а[0][1],а[0][2],а[1][0],а[1][1],а[1][2]. Имя массива а - это константа, которая содержит адрес его первого элемента (для нашего примера - а[0][0]). Предположим, что a= 1000. Тогда адрес элемента а[0][1] будет равен 1002 (элемент типа int занимает в памяти 2 байт), адрес следующего элемента а[0][2]- 1004 и т. п. Что же произойдет, если выбрать элемент, для которого не выделена память. К сожалению, компилятор не следит за этим. В результате возникнет ошибка и программа будет работать неверно.
В языке С существует «сильная» взаимосвязь между указателями и массивами. Любое действие, которое достигается индексированием массива, можно выполнить и с помощью указателей, причем последний вариант будет быстрее. Объявление
int a[5];
определяет массив из пяти элементов а[0],а[1],а[2],а[3],а[4],. Если объект *у объявлен как
int *у
то оператор у=&а[0]; присваивает переменной у адрес элемента а[0]. Если переменная у указывает на очередной элемент массива а, то y + 1 указывает на следующий элемент, причем здесь выполняется соответствующее масштабирование для приращения адреса с учетом длины объекта (для типа int - 2 байт, long - 4 байт, double - 8 байт и т. п.). Так как само имя массива есть адрес его нулевого элемента, то инструкцию y=&a[0]; можно записать ив другом виде: у = а;. Тогда элемент а[i] можно представить как *(а+1). С другой стороны, если у - указатель, то следующие две записи: y[i] и *(у+i) эквивалентны. Между именем массива и соответствующим указателем есть одно важное различие. Указатель - это переменная и y=a; или y++; - допустимые операции. Имя же массива - константа, поэтому конструкции вида а = у; a++; использовать нельзя, так как значение константы постоянно и не может быть изменено.
Переменные с адресами могут образовывать некоторую иерархическую структуру (могут быть многоуровневыми), типа указатель на указатель (т. е. он содержит адрес другого указателя), указатель на указатель на указатель и т. п. Их использование будет рассмотрено ниже на примере.
Если указатели адресуют элементы одного массива, то их можно сравнивать (отношения вида <, >, = =, != и другие работают правильно). В то же время нельзя сравнивать либо использовать в арифметических операциях указатели на разные массивы (соответствующие выражения не приводят к ошибкам при компиляции, но в большинстве случаев не имеют смысла). Как и выше, любой адрес можно проверять на равенство или неравенство со значением NULL. Указатели на элементы одного массива можно также вычитать. Тогда результатом будет число элементов массива, расположенных между уменьшаемым и вычитаемым объектами.
Язык С позволяет инициализировать массив при объявлении. Для этого используется следующая форма:
тип имя_массива[...]...[...] = {список значений};
Рассмотрим примеры:
int a[5]={0,1,2,3,4};
char c[7]={‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’};
int b[2][3]={1,2,3,4,5,6};
b[0][0]=1, b[0][1]=2, b[0][2]=3, b[1][0]=4, b[1][1]=5, b[1][2]=6,
В языке допускаются массивы указателей, которые объявляются, например, следующим образом:
char *m[5];. Здесь m[5] - массив, содержащий адреса элементов типа char.