Views: 8910
Полезные описания переменных
Часто необходимо в памяти расположить последовательно разные виды данных, что бы потом можно было их использовать.
Полезные ссылки
Взято и переработано с сайта
http://www.butovo.com/~zss/cpp/struct.htm
http://cppstudio.com/post/9172/
Синтаксис структур.
Структуры в языке С аналогичны массиву тесно связанных атрибутов. Однако, в отличие от массива, структура позволяет иметь смешанные атрибуты различных типов данных.
Структура создается при помощи ключевого слова struct, за которым следует имя_типа (имя структуры) и список элементов. Описание структуры заканчивается точкой с запятой, т.к. оно является оператором:
struct имя_типа
{
тип_элемента1 имя_элемента1;
тип_элемента2 имя_элемента2;
тип_элемента3 имя_элемента3;
…
};
Пример описания структуры:
struct stboat
{
char type[16]; // тип
char model[16]; // модель
char title[20]; // имя
int year; // год выпуска
double price; // цена
};
Эта структура описывает новый тип данных stboat и содержит три текстовых поля, одно целое и одно действительное.
С описанной структурой не связывается никакая переменная. Для создания новой переменной используется оператор (слово struct является необязательным):
struct имя_структуры имя-переменной;
Для вышеприведенного примера можно создать переменную used_boat:
struct sboat used_boat;
Если со структурой связывается только одна переменная, то ее можно объявить непосредственно в описании структуры перед точкой с запятой. Имя_типа в этом случае можно опустить:
struct
{
char type[16]; // тип
char model[16]; // модель
char title[20]; // имя
int year; // год выпуска
double price; // цена
} used_boat;
Доступ к элементам структуры.
Для обращения к отдельным элементам структуры используется операция обращения к члену структуры – “точка”. Она разделяет имя структурной переменной и имя поля, например
used_boat.year=1955; printf(“%lf”,used_boat.price);
Элементы структуры обрабатываются также, как и любые другие переменные С, необходимо только использовать операцию “точка”.
Можно создавать массивы структур и указатели на структуру, для обращения к элементам структуры предусмотрен оператор “->” (стрелка, он состоит из знаков минус и больше).
sboat boat_array[10]; // описание массива состоящего из 10 структур sboat boat_array[3].year=1980; // sboat *pboat; // описание указателя pboat=&used_boat; // получение адреса структуры pboat->price=12570.25; // загрузка данных в элемент price структуры
Передача структур в функции.
В функцию информация о структуре может передаваться как по значению, так и по ссылке. В первом случае в функцию передается копия структуры, что может снизить эффективность программы.
При передаче по ссылке копирование не выполняется, однако функция получает доступ к элементам структуры и может их изменять.
Можно также использовать указатели на структуру.
Структуры и битовые поля.
В языке С имеется возможность доступа к отдельным разрядам в более крупном типе данных, например в байте. Это полезно, например для изменения масок, установки флагов и т.д. В этом случае описание структуры выглядит следующим образом:
struct имя_типа
{
тип_элемента1
имя_поля1:колич_бит1,
имя_поля2:колич_бит2,
имя_поля3:колич_бит3,
…;
тип_элемента2
…
};
В таких структурах можно использовать только целочисленные типы:
struct keybits
{
unsigned char
shift :1,
ctrl :1,
scrool:1,
lock :1;
};
struct
{
unsigned REIN :1;// выбор режима индикации.
unsigned INPREG :1;// флаг активации входов управления регуляторами
unsigned ALRM :1;// флаг аварии
unsigned BVKLNAF :1;// флаг блокировки одновременного включения нагрузок.
unsigned ENPA :1;// деактивация пароля 1 уровня.
unsigned DISTO :1;// деактивация таймера технического обслуживания
unsigned ERDT :1;// неисправность датчика температуры
unsigned ERDA :1;// сбой данных
} flag;
Объединения.
Объединения – еще один тип данных, которые можно использовать различным образом. К примеру, некоторые данные в одном случае могут рассматриваться как целые, а в другом – как числа с плавающей точкой. По виду объединения напоминают структуры. Объединение тоже содержит несколько типов данных, однако эти данные занимают одну и ту же область памяти.
В структурах описанные данные располагаются последовательно в памяти, а в объединениях они наложены друг на друга.
Например? структура:
struct
{
char type[2]; // тип
char title; // имя
int year; // год выпуска
} used_boat;
Будет располагаться в памяти последовательно
| номер байта | название переменной | тип |
| байт 0 | tipe[0] | char |
| байт 1 | tipe[1] | char |
| байт 2 | title | char |
| байт 3 | year | int |
| байт 4 |
В объединении, например:
union
{
char c;
int ivalue;
long fvalue;
} type1;
расположение переменных в памяти, типа наложение
| номер байта | переменная | c | invalue | fvalue |
| байт 0 | ||||
| байт 1 | ||||
| байт 1 | ||||
| байт 2 |
Переменная с будет иметь значение младшего байта переменных invalue и fvalue…
Объединение создается при помощи ключевого слова union:
union имя_типа
{
тип_элемента1 имя_элемента1;
тип_элемента2 имя_элемента2;
тип_элемента3 имя_элемента3;
…
};
К членам объединения можно обращаться так же, как и к членам структур, либо через операцию “точка”, либо через операцию “->” – для указателей:
union many_types
{
char c[4];
int ivalue[2];
float fvalue;
} type1;
type1.fvalue=1.5;
printf(“%i %i”,type1.ivalue[0],type1.ivalue[1]);
Вариант объединения структур
volatile union
{
struct //
{
unsigned char adhes_RM; //
unsigned char command; //
unsigned char adhes_PU; //
};
struct //
{
unsigned char adhes_RM; //
unsigned char command; //
unsigned char adhes_PU; //
unsigned long nom_rul; //
unsigned char prefiks; //
};
struct //
{
unsigned char adhes_RM; //
unsigned char command; //
unsigned char adhes_PU; //
unsigned int pol_uk; //
};
struct //
{
unsigned char adhes_RM; //
unsigned char command; //
unsigned char adhes_PU; //
unsigned char data[29]; //
};
}cammand_transferMMK;
Хочу обратить внимание на работу некоторых версий компиляторов, возможен вариант, когда компилятор будет выравнивать некоторые переменные по словам данных. Эта проблема решается чисто практически, кода понимаешь, что пишешь одно, а получаешь другое.
в этом варианте, компилятор XC16 v 1.26 разместил данные long с байта 4
struct //
{
unsigned char adhes_RM; // 0 - байт / слово 1
unsigned char command; // 1 /
unsigned char adhes_PU; // 2 / слово 2
// 3 - ? /
unsigned long nom_rul; // 4-5-6-7 / слово 3-4
unsigned char prefiks; // 8 / слово 5
};
Дополнительные средства (typedef и enum).
При помощи оператора typedef можно связать новые типы данных с существующими:
typedef double real;
После такого описания можно использовать real вместо double.
Использовать typedef необходимо с осторожностью. Слишком много новых типов могут ухудшить читаемость программы.
Перечисляемый тип данных enum позволяет определить список последовательных целых чисел, каждое из которых имеет собственное имя. Объявление перечисляемого типа выглядит следующим образом:
enum имя_типа {имя1=знач1, имя2=знач2, имя3=знач3, …}переменная;
Здесь имя1, имя2,… – это имена констант. Им можно присваивать целочисленные значения. Если значения отсутствуют, то предполагается, что они последовательно увеличиваются на единицу, начинаясь с нуля. Память под эти константы во время выполнения не выделяется, поэтому удобно использовать этот оператор для создания констант, если не указывать имя_типа и переменную:
enum (с28=28, с29,с30,c31);
Тип enum часто используется, когда информацию можно представить списком целых значений, подобно номерам дней недели или месяцев в году:
enum months
{Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec}
current_month;
current_month=Dec; //используется константа 12
int diff=(int)current_month-2;
//тип enum автоматически не преобразуется в int
Поскольку имена эквивалентны последовательным целым значениям, то с ними можно выполнять арифметические операции. Фактически в данном примере переменной current_month присваивается целочисленное значение 12.
Создание внешних переменных которые должны быть доступны из подключаемых библиотек
Например есть библиотека spi.h, в ней необходимо описать объединение и сделать так чтобы она была доступна в основной программе
#ifndef XC_HEADER_TEMPLATE_H
#define XC_HEADER_TEMPLATE_H
#include <xc.h> // include processor files - each processor file is guarded.
// описываем объединение
union _Bufer
{
unsigned char dataSPI[4]; // буфер SPI [3][2][1][0]
signed long codacp; // 32 бита
};
// объявляем объединение как обычную переменную (внешнюю), просто вначале дописываем слово union
extern union _Bufer Bufer;
#endif /* XC_HEADER_TEMPLATE_H */
В самом файле где предстоит использовать надо описать
#include "spi.h" //------------------------------------------------------------------------------ union _Bufer Bufer;
дополнение возможно…
Это может быть интересно
Проект с использованием MCC часть 14Views: 1053 С выводом данных на дисплей мы справились (но могу сразу сказать библиотеку графики к этой статьи пришлось доработать, поэтому в этом проекте она обновлена). У нас на текущем …
Контроллер управления светодиодным освещением с дистанционным управлениемViews: 2068 Все активнее светодиоды входят в нашу жизнь. Всё эффективнее становится светодиодное освещение. Всё ниже опускаются цены. Всё больше появляется возможностей получения сочных цветов, простоты в управлении. Всё чаще …
Простой сенсорный регулятор светаViews: 2503 Простой сенсорный регулятор. Проект – 2007 года. Регулятор выполнена на микроконтроллере PIC12F683 и имеет минимальное количество элементов. Выполняет стандартные функции, включение выключение света, изменение яркости, запоминание последнего установленного уровня …
MCC PIC24 – модуль OUTPUT COMPARE – режиме ШИМViews: 1270 Во многих системах управления, для формирования управляющих сигналов требуется модуль ШИМ, он позволяет не только формировать импульсы заданной длительности, но и с применением обычного RC фильтра строить простые …
Altium Designer my Libraries, Project templates, System settings by Catcatcat. V26.0Views: 257 Altium Designer my Libraries, Project templates, System settings by Catcatcat. V26.0 Here I want to share how I configure Altium Designer and how I use the DXPPreferences1.DXPPrf …
Инфракрасный датчик движения, PIR-sensorViews: 3309 Домашняя автоматика предполагает наличие датчиков движения, которые способны контролировать движения человека. Самым простым и доступным устройством позволяющие контролировать изменения ИК-излучения, это ПИР-сенсоры. На текущий момент доступны не дорогие модели D203B, D204B, D205B. Все …
BMP280 – температура и атмосферное давление – учебный проектViews: 2272 Учебный проект на PIC32 и светодиодной панели P5 (2121)-168-6432-80 (32*64). Проект позволяет ознакомиться с простой графикой и с чтением давления и температуры с датчика BMP280. Для тестирования необходимо …
Стробоскоп для автомобиляViews: 2244 Одним из популярных решений светового тюнинга автомобиля, мотоцикла или скутера стал эффект – “полицейский стробоскоп“. На база платы ch-c0050 реализовано несколько проектов. В этой статье приводятся две версии …
Kitchen timer with contactless gesture controlViews: 785 Кухонний таймер з безконтактним керуванням жестами дозволяє встановити необхідний період часу для приготування страв, не торкаючись пристрою. Дуже зручно під час приготування їжі, коли руки забрудниться. Усі …
MPLAB® Harmony – или как это просто! Часть 4.Views: 2389 Часть четвертая – это может показаться немного сложно. Структура проекта. Для облегчения конфигурирования проекты MPLAB Harmony обычно структурированы таким образом, чтобы изолировать код, необходимый для настройки «системы», от …