- •1.Структура пэвм. Размещение данных и программ в памяти пэвм. Биты, байты. Программа, машинная команда
- •2.Состав программного обеспечения технических средств. Среда программирования
- •6. Компоновка программных модулей и запись программной кодировки в целевое устройство.
- •10. Понятие алгоритмов и способы их описания
- •2.5. Графическое описание алгоритма
- •20. Вещественные типы данных (с плавающей точкой).
- •Int I; // целый тип
- •29. Оператор выбора альтернатив switch
- •34. Операции сравнения. Логические операции. Унарные операции Операции сравнения
- •33. Побитовые логические операции, операции над битами
- •39. Стандартная библиотека языка си. Вывод данных
- •41. Ввод-вывод потоками
- •42. Препроцессор. Директивы #include, #define, #if...
- •45. Структуры. Вложенные структуры
- •Int day, month, year;
- •52.Операции typedef и sizeof.
- •Void f1(int m[3][4]) {
- •70. Интерфейс программирования jtag
45. Структуры. Вложенные структуры
При разработке программ важным является выбор эффективного способа представления данных. Во многих случаях недостаточно объявить простую переменную или массив, а нужна более гибкая форма представления данных. Таким элементом может быть структура, которая позволяет включать в себя разные типы данных, а также другие структуры. Полем структурной переменной может быть переменная любого типа, в том числе другая структурная переменная. Поле, представляющее собой структуру, называется вложенной структурой.
Тип вложенной структуры должен быть объявлен раньше. Кроме того, структура не может быть вложена в структуру того же типа.
46. Массивы структур. Битовые поляСтруктурный тип «struct ID_структуры», как правило, используют для декларации массивов, элементами которых являются структурные переменные. Это позволяет создавать программы, оперирующие с простейшими базами данных. Например, массив структур, объявленного ранее типа:
struct Person spisok[100];
причем ключевое слово struct можно не писать. Декларацию массива можно выполнить и в описании шаблона следующим образом:
struct Рerson {
char fio[40];
Int day, month, year;
} spisok[100];
В данном случае обращение к полю, например, day элемента массива с индексом i может быть выполнено одним из следующих способов:
spisok[i].day=22; *(spisok+i).day=22; (spisok+i)–>day=22;
Пример. Приведем часть программы, иллюстрирующей создание массива структур и передачу структурных данных в функции:
struct Spisok {
char Fio[20];
double S_Bal;
};
// Описание прототипов функций пользователя
void Out(int, Spisok);
void In(int, Spisok *);
void main(void)
{
Spisok Stud[50], *sved;
. . .
for(i=0;i<N;i++)
Vvod(i, &Stud[i]);
puts("\n Spisok Students");
for(i=0;i<N;i++)
Out(i+1, Stud[i]);
. . .
}
// Функция вывода на экран данных одного элемента структуры
void Out(int nom, Spisok dan) {
printf("\n %3d – %20s %4.2lf ",nom, dan.Fio, dan.S_Bal);
}
// Функция ввода данных одного элемента структуры
void In (int nom, Spisok *sved) {
printf("\n Введите сведения %d : ", nom+1);
fflush(stdin);
puts("\n ФИО – ");
gets(sved–>Fio);
puts("\n Средний балл – ");
scanf(“%lf”, &sved–>S_Bal);
}
Битовые поля – это особый вид полей структуры. Они используются для плотной упаковки данных, например, флажков типа «да/нет». Минимальная адресуемая ячейка памяти – 1 байт, а для хранения флажка достаточно одного бита. При описании битового поля после имени через двоеточие указывается длина поля в битах (целая положительная константа), не превышающая разрядности поля типа int.
47. Объединения. Перечисления Объединение – поименованная совокупность данных разных типов, размещаемых с учетом выравнивания в одной и той же области памяти, размер которой достаточен для хранения наибольшего элемента. Объединенный тип данных декларируется подобно структурному типу:
union ID_объединения {
описание полей
};
Пример описания объединенного типа:
union word {
int nom;
char str[20];
};
Пример объявления объектов объединенного типа:
union word *p_w, mas_w[100];
Объединения применяют для экономии памяти в случае, когда объединяемые элементы логически существуют в разные моменты времени либо требуется разнотипная интерпретация поля данных. Практически все вышесказанное для структур имеет место и для объединений. Декларация данных типа union, создание переменных этого типа и обращение к полям объединений производится аналогично структурам. Перечисления – средство создания типа данных посредством задания ограниченного множества значений. Определение перечисляемого типа данных имеет вид
enum ID_перечисляемого_типа {
список_значений };
Значения данных перечисляемого типа указываются идентификаторами, например:
enum marks {
zero, one, two, three, four, five };
Компилятор последовательно присваивает идентификаторам списка значений целочисленные величины 0, 1, 2,... . При необходимости можно явно задать значение идентификатора, тогда очередные элементы списка будут получать последующие возрастающие значения. Основные операции с данными перечисляемого типа: – присваивание переменных и констант одного типа; – сравнение для выявления равенства либо неравенства. Практическое назначение перечисления – определение множества различающихся символических констант целого типа.
48. Указатели. Указатели и адреса объектов. Указатели и массивы. При обработке декларации любой переменной, например double x=1.5; компилятор выделяет для переменной участок памяти, размер которого определяется ее типом (double – 8 байт), и инициализирует его указанным значением (если таковое имеется). Далее все обращения в программе к переменной по имени заменяются компилятором на адрес участка памяти, в котором будет храниться значение этой переменной. Разработчик программы на языке Си имеет возможность определить собственные переменные для хранения адресов участков оперативной памяти. Такие переменные называются указателями. Итак, указатель – это переменная, которая может содержать адрес некоторого объекта. Простейшая декларация указателя имеет формат
тип * ID_указателя;
Например: int *a; double *f; char *w;
Здесь тип может быть любым, кроме ссылки или битового поля. Символ «звездочка» относится непосредственно к ID указателя, поэтому для того, чтобы декларировать несколько указателей, ее нужно записывать перед именем каждого из них. Например, в декларации:
int *a, *b, с;
определены два указателя на участки памяти для целочисленных данных, а также обычная целочисленная переменная с. Значение указателя равно первому байту участка памяти, на который он ссылается. Указатели предназначены для хранения адресов областей памяти. В языке Cи имеются три вида указателей – указатели на объект известного типа, указатель типа void и указатель на функцию. Эти три вида различаются как своими свойствами, так и набором допустимых операций. Указатель не является самостоятельным типом данных, так как всегда связан с каким-либо конкретным типом, т.е. указатель на объект содержит адрес области памяти, в которой хранятся данные определенного типа. Указатель типа void применяется в тех случаях, когда конкретный тип объекта, адрес которого требуется хранить, не определен (например, если в одной и той же переменной в разные моменты времени требуется хранить адреса объектов различных типов). Указателю типа void можно присвоить значение указателя любого типа, а также сравнивать его с любыми другими указателями, но перед выполнением каких-либо действий с участком памяти, на которую он ссылается, требуется явно преобразовать его к конкретному типу. Указатель может быть константой или переменной, а также указывать на константу или переменную. С указателями-переменными связаны две унарные операции & и *. Операция & означает «взять адрес» операнда. Операция * имеет смысл – «значение, расположенное по указанному адресу» (операция разадресации).Таким образом, обращение к объектам любого типа как операндам операций в языке Cи может производиться: – по имени (идентификатору); – по указателю (операция косвенной адресации)
50. Операции с указателями: сложение и вычитание, инкремент и декремент, сравнение указателей Помимо уже рассмотренных операций, с указателями можно выполнять арифметические операции сложения, инкремента (++), вычитания, декремента (--) и операции сравнения. Арифметические операции с указателями автоматически учитывают размер типа величин, адресуемых указателями. Эти операции применимы только к указателям одного типа и имеют смысл в основном при работе со структурами данных, последовательно размещенными в памяти, например с массивами. Инкремент перемещает указатель к следующему элементу массива, декремент – к предыдущему. Указатель, таким образом, может использоваться в выражениях вида
p # iv, ## p, p ##, p # = iv,
p – указатель, iv – целочисленное выражение, # – символ операции '+' или '–'. Результатом таких выражений является увеличенное или уменьшенное значение указателя на величину iv * sizeof(*p), т.е. если указатель на определенный тип увеличивается или уменьшается на константу, его значение изменяется на величину этой константы, умноженную на размер объекта данного типа. Текущее значение указателя всегда ссылается на позицию некоторого объекта в памяти с учетом правил выравнивания для соответствующего типа данных. Таким образом, значение p # iv указывает на объект того же типа, расположенный в памяти со смещением на iv позиций. При сравнении указателей могут использоваться отношения любого вида («>», «<» и т.д.), но наиболее важными видами проверок являются отношения равенства и неравенства («==», «!=»). Отношения порядка имеют смысл только для указателей на последовательно размещенные объекты (элементы одного массива). Разность двух указателей дает число объектов адресуемого ими типа в соответствующем диапазоне адресов, т.е. в применении к массивам разность указателей, например, на третий и шестой элементы равна 3. Очевидно, что уменьшаемый и вычитаемый указатели должны принадлежать одному массиву, иначе результат операции не имеет практической ценности и может привести к непредсказуемому результату. То же можно сказать и о суммировании указателей. Значение указателя можно вывести на экран с помощью функции printf, используя спецификацию %p (pointer), результат выводится в шестнадцатеричном виде.
51. Работа с динамической памятью. Динамические массивы. В языке Си размерность массива при объявлении должна задаваться константным выражением. При необходимости работы с массивами переменной размерности вместо массива достаточно объявить указатель требуемого типа и присвоить ему адрес свободной области памяти (захватить память). После обработки массива занятую память надо освободить. Библиотечные функции работы с памятью описаны в файле alloc.h. Пример создания динамического массива:
float *x;
int n;
printf("\nРазмерность - "); scanf(" %d",&n);
if ((x = calloc(n, sizeof(*x)))==NULL) { // Захват памяти
printf("\n Предел размерности “);
exit(1); }
else {
printf("\n Массив создан !");
...
for (i=0; i<n; i++)
printf("\n%f",x[i]);
...
free(x); // Освобождение памяти
}
В С++ введены две операции: захват памяти - new и освобождение захваченной ранее памяти - delete.Общий формат записи: указатель = new тип (значение); Пример создания одномерного динамического массива Массив объявляем указателем.
...
double *x;
int i, n;
...
puts(" Введите размер массива: ");
scanf(“%d”, &n);
x = new double [n] ;
if (x == NULL) {
puts(" Предел размерности ! ");
return; }
for (i=0; i<n; i++) // Ввод элементов массива
scanf(“%lf”, &x[i]);
...
delete [ ]x; // Освобождение памяти
