- •Конспект лекций Часть 2 Оглавление
- •Часть 2 1
- •8. Указатели
- •8.1. Указатели Понятие указателя
- •Работа с указателями
- •Арифметика указателей
- •Ошибки при работе с указателями
- •If (p1) // Если указатель не равен 0, то все в порядке
- •8.2. Указатели и массивы
- •9. Функции и структура программы
- •9.1. Создание и использование функций Процедурный подход к разработке программ
- •Определение функций в программе
- •Завершение работы функции (инструкция return)
- •If ( Ошибка )
- •Список параметров функций
- •Обращение к функциям в программе
- •Передача данных по значению
- •Передача данных с помощью указателей
- •Передача данных по ссылке
- •Перегружаемые функции
- •Параметры по умолчанию
- •Функции с переменным числом параметров
- •Рекурсивное использование функций
- •Передача функций в качестве параметров
- •Встраиваемые функции (inline - функции)
- •Прототипы функций
- •9.2. Структура программы. Глобальные и локальные данные (области видимости и время жизни) Структура программы
- •Глобальные и локальные данные
- •Классы памяти
- •Доступ к полям структур
- •Указатели на структуры
- •Структурные параметры функций
- •Битовые поля структур
- •10.2. Объединения Обычные объединения
- •Анонимные объединения
- •10.3. Перечисления
- •Void WriteColor (тип_Спектр c )
- •11. Организация ввода/вывода и работа с файлами
- •11.1. Потоки для работы с файлами Общие сведения
- •Пример работы с файлом
- •Создание потока, открытие и закрытие файла
- •Запись и чтение данных в текстовых файлах
- •Запись и чтение данных в двоичном режиме
- •If ( !File ) // Проверили удалось ли открыть файл
- •Как обнаружить конец файла?
- •Прямой доступ при работе с файлами
- •If ( !File ) // Проверили удалось ли открыть файл
- •Статус потоков ввода-вывода
- •Некоторые другие функции управления потоками ввода-вывода
- •Примеры по работе с файлами
- •12. Работа с динамической памятью Распределение памяти при работе программы
- •Динамическое выделение и освобождение памяти в стиле c
- •Возможные ошибки при работе с динамической памятью
- •Динамические массивы
- •Продолжение следует …
Битовые поля структур
Для более экономного использования памяти очень часто используют побитное хранение числовых и логических значений. Такой способ хранения данных можно реализовать на основе использования побитовых операций. Однако существует и другой метод доступа к отдельным битам памяти – с помощью битовых полей структур. Например:
struct Date
{
unsigned WeekDay : 3; // 0..7 (3 бита)
unsigned MonthDay : 5; // 0..31 (5 бит)
unsigned Month : 4; // 0..12 (4 бита)
unsigned Year : 12; // 0..4048 (12 бит)
} D1;
Под переменную D1 в памяти будет отведено всего 4 байта:
0 … 2 |
3 … 7 |
8 … 11 |
12 … 23 |
24 … 31 |
WeekDay |
MonthDay |
Month |
Year |
Не используется |
3 бита |
5 бит |
4 бита |
12 бит |
8 бит |
Число, указанное в определении поля после двоеточия, определяет количество бит, отведенных под соответствующее битовое поле. Тип битового поля определяет способ интерпретации этого поля в программе.
Для хранения логического значения под битовое поле отводится 1 бит:
struct Flags
{
bool b1: 1;
bool b2: 1;
bool b3: 1;
bool b4: 1;
bool b5: 1;
bool b6: 1;
bool b7: 1;
bool b8: 1;
} Fl;
Под переменную Fl в памяти будет отведен 1 байт. Таким образом, в одном байте памяти можно разместить 8 логических значений.
Обращение к битовым полям осуществляется так же, как и к обычным полям структур:
D1.WeekDay = 4;
D1.MontthDay = 25;
D1.Month = 9;
D1.Year = 2004;
В одной структуре можно совместно использовать и обычные и битовые поля.
10.2. Объединения Обычные объединения
Объединения – это две или более переменных расположенных по одному адресу (говорят, что они разделяют одну и ту же память). Объединения определяются подобно структурам, но только с использованием ключевого слова union:
union t_num{
int i;
double d;
};
Здесь описан новый тип данных с именем t_num, представляющий собой объединение двух членов (полей, элементов), каждый из которых задан типом данных и именем. Члены объединений могут быть любых типов, а их количество – любым.
Для работы с объединением следует определить соответствующие переменные:
t_num A, B; // Определены две переменные А и В
Создание переменных модно совместить с описанием объединения:
union t_num{
int i;
double d;
} A, B; // Описан тип данных t_num и определены две переменные А и В
Обращение к полям объединения осуществляется так же, как и к элементам структуры – с использованием оператора “точка”:
A.i = 13;
B.d = 3.14;
cout << A.i + B.d;
Если обращение к полям объединения осуществляется через указатель, то необходимо использовать оператор “стрелка”:
t_num *p = &A; // Указатель на объединение р инициализирован адресом переменной А
p -> d = 234.33; // Полю d переменной А присвоено новое значение
Передача объединений в качестве аргументов функций осуществляется точно так же, как и для структур.
В памяти члены объединения “накрывают” друг друга (располагаются по одному адресу):
Если вывести на экран адреса переменной А и полей i и d
cout << &A << " " << &A.i << " " << &A.d << endl;
то будут выведены три одинаковых адреса.
Объединения не могут хранить одновременно несколько различных значений, они позволяют интерпретировать несколькими различными способами содержимое одной и той же области памяти.
Например, необходимо написать функцию обеспечивающую перестановку младшего и старшего байта короткого целого:
short Swap ( short I)
{
union t_U {
short i;
char c [2];
} u;
u.i = I;
char ch = u.c [0];
u.c [0] = u.c [1];
u.c [1] = ch;
return u.i;
}
cout << Swap (1234) << endl; // На экране -11772
Переменная u из этой функции интерпретируется в памяти так: