- •Вопрос1)Общая структура программы на языке Си.
- •1.Внутреннее представление данных в оперативной памяти;
- •2.Совокупность значений (диапазон), которые могут принимать данные этого типа;
- •3.Набор операций, которые допустимы над такими данными.
- •Вопрос2)Константы в программах
- •Вопрос3)Операции, выражения
- •Вопрос 4
- •Вопрос 5
- •Вопрос 6 Общая структура программы на языке Си.
- •Вопрос 7
- •Вопрос 8 Арифметические операции
- •Вопрос 9
- •Вопрос 10
- •If (выражение) оператор;
- •If (выражение) оператор 1 ;
- •If (выражение 1) оператор 1;
- •If (выражение 2) оператор 2;
- •If (выражение 3) оператор 3;
- •Вопрос 11
- •Вопрос 12
- •Вопрос 13
- •Вопрос 14
- •Вопрос 15
- •Вопрос 16
- •Вопрос 17
- •Вопрос 19 Операция sizeof
- •Вопрос 20
- •Вопрос 21
- •Вопрос 22 Связь указателей и массивов.
- •Вопрос 23
- •Вопрос 24
- •Вопрос 25 Массивы структур
- •Вопрос 26
- •Вопрос 27
- •Вопрос 28
- •Вопрос 29
- •Вопрос 30
- •Вопрос 31
- •Закрытие файла
- •Вопрос 32
- •Вопрос 33 Вложенные структуры
- •Вопрос 34 Массивы структур
- •Вопрос 35 Размещение структурных переменных в памяти
- •Вопрос 36
- •Вопрос 37
- •Вопрос 38
- •Вопрос 39
Вопрос 21
Указатели на указатели.
В языке Си можно описать и переменную типа «указатель на указатель». Это ячейка оперативной памяти, в которой будет храниться адрес указателя на какую либо переменную. Признак такого типа данных – повторение символа «*» перед идентификатором переменной. Количество символов «*» определяет уровень вложенности указателей друг в друга. При объявлении указателей на указатели возможна их одновременная инициализация. Например:
int y=5;
int *p1=&y;
int **pp1=&p1;
int ***ppp1=&pp1;
Теперь присвоим целочисленной переменной y новое значение, например 10. Одинаковое присваивание произведут следующие операции:
y=10; *p1=10; **pp1=10; ***ppp1=10;
Для доступа к области ОП, отведенной под переменную y можно использовать и индексы. Справедливы следующие аналоги:
*p1 p1[0] **pp1 pp1[0][0] ***ppp1 ppp1[0][0][0]
Многомерные массивы
Многомерные массивы отличаются от одномерных только тем, что каждый элемент характеризуется не одним, а двумя или более индексами. Они используются, например, для хранения таблиц (каждый элемент таблицы имеет 2 индекса - № строки и № столбца).
Декларация многомерного массива имеет следующий формат:
тип ID [размер1] [размер2]…[размерN] =
{ {список начальных значений},
{список начальных значений},…
};
Списки начальных значений – атрибут необязательный.
Пример:
int a[3][3]={ {1,2,3}, {4,5,6}, {7,8,9} };
Аналогично, при обращении к конкретному элементу многомерного массива указывается имя массива и затем - последовательно индексы элемента, каждый в квадратных скобках; например:
a[2][1]
a[i+1][k]
Рассмотрим особенности работы с многомерными массивами на конкретном примере двумерного массива (двумерные массивы называют также матрицами):
#include <stdio.h>
void main()
{
int i, j;
int m[3][4] = { { 1, 2, 3, 4}, {11,12,13,14}, {21,22,23,24} };
for (i=0; i<3; i++) {
printf("\n %2d)", i+1);
for (j=0; j<4; j++)
printf(" %3d",m[ i ] [ j ]);
}
}
Результаты работы программы:
2 3 4
2 13 14
3)21 22 23 24
Вопрос 22 Связь указателей и массивов.
Идентификатор массива указывает адрес памяти, начиная с которого он расположен, т.е. адрес его первого элемента. Работа с массивами тесно связана с применением указателей.
Пусть объявлен массив a из 5 целочисленных элементов:
int a[5];
a
-
a[0]
a[1]
a[2]
a[3]
a[4]
4000 4004 4008 4012 4016
Здесь приведено символическое изображение оперативной памяти, выделенной компилятором для объявленного целочисленного массива а[5]. Адрес массива выбирается компилятором в зависимости от размера доступной памяти, наличия других переменных и массивов и др. Для конкретности, здесь положено значение адреса, равное 4000. В реальной программе вместо 4000 может быть другое значение, но относительное положение элементов массива всегда остается постоянным.
В языке С идентификаторы массивов считаются константными указателями (т.е. в данном примере а "имеет значение" 4000). Такую константу можно присвоить переменной типа указатель, но нельзя подвергать преобразованиям, например:
int a[5], *q;
q = a; // Правильно - присваивание константы переменной
a = q; // Ошибка: в левой части - указатель-константа
Именно потому, что имена массивов считаются константными указателями, в языке Си нельзя непосредственно присваивать массивы друг другу (хотя структуры, включающие массивы как поля, целиком присваивать друг другу можно!)
Однако операция sizeof для массивов все же дает размер массива, а не указателя:
int n = sizeof(a) / sizeof(*a);
// n=5, т.к. sizeof(a)=20, sizeof(int)=4
int m = sizeof(q) / sizeof(*q);
// m=1, т.к. sizeof(int*)=4, sizeof(int)=4