- •1.2 Функции пользователя
- •1.2.1 Общие моменты
- •1.2.2 Изменение переменных в функции из других функций
- •1.2.3 Рекурсивные вызовы функций
- •1.2.4 Функции с переменным количеством параметров
- •1.2.5 Перегрузка функций
- •1.2.6 Передача функций в качестве параметров
- •1.3 Структуры
- •1.4 Битовые поля
- •1.5 Объединения
- •2 Оператор описания типа
- •3 Оператор описания объекта
- •3.1 Классы памяти
- •4 Преобразование типов
- •4.2.1 Неявные преобразования
- •4.2.2 Явные преобразования
- •5 Директивы препроцессора языка си
1.4 Битовые поля
Структуру можно использовать для обеспечения доступа к отдельным битам слова при помощи битовых полей.
Использовать битовые поля можно при разработке программ, в которых важно экономить память, или системных программ, прямо взаимодействующих с оборудованием, в частности при написании драйверов устройств может понадобиться доступ к конкретным битам регистра устройства.
Целые компоненты структуры можно объявить битовыми полями шириной от 1 до 16 битов.
Битовое поле задается следующим образом:
тип <имя поля>: ширина;
где тип - это char, unsigned char, int или unsigned int .
Если имя битового поля опущено, то число битов, заданное выражением ширина, распределяется в памяти, но поле при этом остается недоступным программе. Если при этом значение ширина равно нулю, то следующее поле будет начинаться со следующего слова памяти.
Пример:
struct str {
int i: 3;
unsigned j: 4;
int : 4
int k: 2;
} a;
Для указанных в структуре полей задается следующее распределение памяти:
15 14 12 11 10 9 8 7 6 5 4 3 2 1 0
x x x x x x x x x x x x x x x
< -- > < -------- > < -------- > < ---- >
k не испол. j i
Целые поля хранятся в виде дополнения до 2, причем крайний левый бит является старшим. Для битового поля типа int (например, signed) старший бит интерпретируется как знаковый. Например, поле k типа signed int шириной 1 может содержать только значения –1 и 0, так как битовой шаблон 1 будет интерпретироваться как -1.
Пример:
#include<stdio.h>
void main (void)
{
struct str {
int i:1;
unsigned int j:4;
int l:4;
int k:2;
} a;
a.i=1;
printf(“%d”,a.i);
}
Результат работы программы: -1.
1.5 Объединения
Объединения подобны структурам. Но в каждый момент времени может использоваться (или являться активным) только один из его компонентов.
Объединение может быть задано следующим шаблоном:
union {
описание компонента 1;
описание компонента 2;
}
Для каждого их этих компонентов выделяется одна и та же область памяти.
Доступ к компонентам объединения осуществляется также как и к элементам структуры.
Примеры:
union {
float radius; окружность
float a[2]; прямоугольник
int b[3]; треугольник
position p;
} geom_fig;
Объединения применяются для: минимизации используемого объема памяти, если в каждый момент времени только один объект из многих является активным.
2 Оператор описания типа
Используется для того, чтобы все свойства объекта собрать в одном месте и присвоить им имя. Это имя типа может затем использоваться для последующих описаний других объектов.
Описания типа имеет следующую форму:
typedef спецификатор типа имя нового типа;
спецификатор типа – основной или производный тип, или тип, ранее определенный программистом.
Примеры:
typedef float miles, speed;
имена miles и speed описаны как синонимы для имени float.
typedef float a[5], *p;
typedef struct {float x, y;}point;
С помощью этих типов можно определять объекты точно так же, как с помощью типов float и int. Например так
point s1, s2, *p;