- •Раздел 1. Основы программирования на языке си
- •1) Для решения каких задач может применяться смешанное программирование?
- •2) Назовите основные типы данных на языке Си. Приведите примеры.
- •Целый тип данных
- •Данные плавающего типа
- •4) Условные выражения. Операторы выбора. Приведите примеры.
- •Оператор if
- •Выбор из нескольких возможностей: if...Else if...
- •Оператор switch
- •5) Основные циклические конструкции. Пост- и пред- условия. Приведите примеры.
- •6) Структурное программирование. Определение. Основы концепции.
- •7) Динамическая память. Основные команды. Приведите примеры.
- •Пример: печать n первых простых чисел
- •8) Массивы. Определение. Примеры инициализации одно- и двух- мерных массивов.
- •9) Структура программ на языке Си. Основные типы файлов.
- •Библиотечные заголовочные файлы ansi Си
- •Указатели
- •11) Опишите работу следующих операторов: break, goto, continue, default, return. Оператор goto
- •Оператор return
- •Оператор break
- •Оператор continue
7) Динамическая память. Основные команды. Приведите примеры.
Помимо статической и стековой памяти, существует еще практически неограниченный ресурс памяти, которая называется динамическая, или куча ( heap ). Программа может захватывать участки динамической памяти нужного размера. После использования ранее захваченный участок динамической памяти следует освободить.
Под динамическую память отводится пространство виртуальной памяти процесса между статической памятью и стеком. Обычно стек располагается в старших адресах виртуальной памяти и растет в сторону уменьшения адресов. Программа и константные данные размещаются в младших адресах, выше располагаются статические переменные. Пространство выше статических переменных и ниже стека занимает динамическая память:
Структура динамической памяти автоматически поддерживается исполняющей системой языка Си. Динамическая память состоит из захваченных и свободных сегментов, каждому из которых предшествует описатель сегмента. При выполнении запроса на захват памяти исполняющая система производит поиск свободного сегмента достаточного размера и захватывает в нем отрезок требуемой длины. При освобождении сегмента памяти он помечается как свободный, при необходимости несколько подряд идущих свободных сегментов объединяются.
В языке Си для захвата и освобождения динамической памяти применяются стандартные функции malloc и free, описания их прототипов содержатся в стандартном заголовочном файле "stdlib.h". (Имя malloc является сокращением от memory allocate - "захват памяти".) Прототипы этих функций выглядят следующим образом:
void *malloc(size_t n); // Захватить участок памяти
// размером в n байт
void free(void *p); // Освободить участок
// памяти с адресом p
Здесь n - это размер захватываемого участка в байтах, size_t - имя одного из целочисленных типов, определяющих максимальный размер захватываемого участка. Тип size_t задается в стандартном заголовочном файле " stdlib.h " с помощью оператора typedef (см. c. 117). Это обеспечивает независимость текста Си-программы от используемой архитектуры. В 32-разрядной архитектуре тип size_t определяется как беззнаковое целое число:
typedef unsigned int size_t;
Функция malloc возвращает адрес захваченного участка памяти или ноль в случае неудачи (когда нет свободного участка достаточно большого размера). Функция free освобождает участок памяти с заданным адресом. Для задания адреса используется указатель общего типа void*. После вызова функции malloc его необходимо привести к указателю на конкретный тип, используя операцию приведения типа, см. раздел 3.4.11. Например, в следующем примере захватывается участок динамической памяти размером в 4000 байтов, его адрес присваивается указателю на массив из 1000 целых чисел:
int *a; // Указатель на массив целых чисел
. . .
a = (int *) malloc(1000 * sizeof(int));
Выражение в аргументе функции malloc равно 4000, поскольку размер целого числа sizeof(int) равен четырем байтам. Для преобразования указателя используется операция приведения типа (int *) от указателя обобщенного типа к указателю на целое число.