Полезные описания переменных
Часто необходимо в памяти расположить последовательно разные виды данных, что бы потом можно было их использовать.
Полезные ссылки
Взято и переработано с сайта
http://www.butovo.com/~zss/cpp/struct.htm
http://cppstudio.com/post/9172/
Синтаксис структур.
Структуры в языке С аналогичны массиву тесно связанных атрибутов. Однако, в отличие от массива, структура позволяет иметь смешанные атрибуты различных типов данных.
Структура создается при помощи ключевого слова struct, за которым следует имя_типа (имя структуры) и список элементов. Описание структуры заканчивается точкой с запятой, т.к. оно является оператором:
1 2 3 4 5 6 7 |
struct имя_типа { тип_элемента1 имя_элемента1; тип_элемента2 имя_элемента2; тип_элемента3 имя_элемента3; … }; |
Пример описания структуры:
1 2 3 4 5 6 7 8 |
struct stboat { char type[16]; // тип char model[16]; // модель char title[20]; // имя int year; // год выпуска double price; // цена }; |
Эта структура описывает новый тип данных stboat и содержит три текстовых поля, одно целое и одно действительное.
С описанной структурой не связывается никакая переменная. Для создания новой переменной используется оператор (слово struct является необязательным):
1 |
struct имя_структуры имя-переменной; |
Для вышеприведенного примера можно создать переменную used_boat:
1 |
struct sboat used_boat; |
Если со структурой связывается только одна переменная, то ее можно объявить непосредственно в описании структуры перед точкой с запятой. Имя_типа в этом случае можно опустить:
1 2 3 4 5 6 7 8 |
struct { char type[16]; // тип char model[16]; // модель char title[20]; // имя int year; // год выпуска double price; // цена } used_boat; |
Доступ к элементам структуры.
Для обращения к отдельным элементам структуры используется операция обращения к члену структуры – “точка”. Она разделяет имя структурной переменной и имя поля, например
1 2 |
used_boat.year=1955; printf(“%lf”,used_boat.price); |
Элементы структуры обрабатываются также, как и любые другие переменные С, необходимо только использовать операцию “точка”.
Можно создавать массивы структур и указатели на структуру, для обращения к элементам структуры предусмотрен оператор “->” (стрелка, он состоит из знаков минус и больше).
1 2 3 4 5 |
sboat boat_array[10]; // описание массива состоящего из 10 структур sboat boat_array[3].year=1980; // sboat *pboat; // описание указателя pboat=&used_boat; // получение адреса структуры pboat->price=12570.25; // загрузка данных в элемент price структуры |
Передача структур в функции.
В функцию информация о структуре может передаваться как по значению, так и по ссылке. В первом случае в функцию передается копия структуры, что может снизить эффективность программы.
При передаче по ссылке копирование не выполняется, однако функция получает доступ к элементам структуры и может их изменять.
Можно также использовать указатели на структуру.
Структуры и битовые поля.
В языке С имеется возможность доступа к отдельным разрядам в более крупном типе данных, например в байте. Это полезно, например для изменения масок, установки флагов и т.д. В этом случае описание структуры выглядит следующим образом:
1 2 3 4 5 6 7 8 9 10 |
struct имя_типа { тип_элемента1 имя_поля1:колич_бит1, имя_поля2:колич_бит2, имя_поля3:колич_бит3, …; тип_элемента2 … }; |
В таких структурах можно использовать только целочисленные типы:
1 2 3 4 5 6 7 8 |
struct keybits { unsigned char shift :1, ctrl :1, scrool:1, lock :1; }; |
1 2 3 4 5 6 7 8 9 10 11 |
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; |
Объединения.
Объединения – еще один тип данных, которые можно использовать различным образом. К примеру, некоторые данные в одном случае могут рассматриваться как целые, а в другом – как числа с плавающей точкой. По виду объединения напоминают структуры. Объединение тоже содержит несколько типов данных, однако эти данные занимают одну и ту же область памяти.
В структурах описанные данные располагаются последовательно в памяти, а в объединениях они наложены друг на друга.
Например? структура:
1 2 3 4 5 6 |
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 |
В объединении, например:
1 2 3 4 5 6 |
union { char c; int ivalue; long fvalue; } type1; |
расположение переменных в памяти, типа наложение
номер байта | переменная | c | invalue | fvalue |
байт 0 | ||||
байт 1 | ||||
байт 1 | ||||
байт 2 |
Переменная с будет иметь значение младшего байта переменных invalue и fvalue…
Объединение создается при помощи ключевого слова union:
1 2 3 4 5 6 7 |
union имя_типа { тип_элемента1 имя_элемента1; тип_элемента2 имя_элемента2; тип_элемента3 имя_элемента3; … }; |
К членам объединения можно обращаться так же, как и к членам структур, либо через операцию “точка”, либо через операцию “->” – для указателей:
1 2 3 4 5 6 7 8 9 10 |
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]); |
Вариант объединения структур
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
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
1 2 3 4 5 6 7 8 9 |
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 можно связать новые типы данных с существующими:
1 |
typedef double real; |
После такого описания можно использовать real вместо double.
Использовать typedef необходимо с осторожностью. Слишком много новых типов могут ухудшить читаемость программы.
Перечисляемый тип данных enum позволяет определить список последовательных целых чисел, каждое из которых имеет собственное имя. Объявление перечисляемого типа выглядит следующим образом:
1 |
enum имя_типа {имя1=знач1, имя2=знач2, имя3=знач3, …}переменная; |
Здесь имя1, имя2,… – это имена констант. Им можно присваивать целочисленные значения. Если значения отсутствуют, то предполагается, что они последовательно увеличиваются на единицу, начинаясь с нуля. Память под эти константы во время выполнения не выделяется, поэтому удобно использовать этот оператор для создания констант, если не указывать имя_типа и переменную:
1 |
enum (с28=28, с29,с30,c31); |
Тип enum часто используется, когда информацию можно представить списком целых значений, подобно номерам дней недели или месяцев в году:
1 2 3 4 5 6 |
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, в ней необходимо описать объединение и сделать так чтобы она была доступна в основной программе
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#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 */ |
В самом файле где предстоит использовать надо описать
1 2 3 4 |
#include "spi.h" //------------------------------------------------------------------------------ union _Bufer Bufer; |
дополнение возможно…
Это может быть интересно
I2C MODULE – PIC18F25K42 Device ID Revision = A001
I2C MODULE Обход ошибок в версии I2C MODULE – PIC18F25K42 Device ID Revision = A001 В Серии K42 применен совершенно новый модуль шины I2C, который позволяет поддерживать все режимы этой …Гаджеты для домашней автоматики – Датчик приближения
Управление светодиодным освещением – Датчик приближения. Данный гаджет предназначен для управления внутренним освещением мебели. Датчик позволяет определить закрытие или открытие дверцы или ящика и при этом включать или выключать освещение. …Просто о структурах и объединениях в Си
Какие задачи нам позволяют решать структуры и объединения? Для разработчика встроенных систем эффективность и компактность кода всегда на первом месте. Если программировании на Ассемблере ты сам определяешь как и где …VU Meter Tower ART
Стерео индикатор уровня аудио сигнала. Компактность и удобство проектирования устройств на светодиодах WS2812B, а также легкость реализации алгоритма родило идею созданию своей конструкции. В этом проекте я предоставлю все материалы …Часы + Календарь + Термометр + …
Часы + Календарь + Термометр + Индикатор влажности + Секундомер + Дистанционное управление на ИК лучах (пульты на RC-5 протоколе) + Автоматическая регулировка яркости + Возможность вывода данных через USB, на плате ILLISSI_B4_primum …LCD индикаторы на драйвере ML1001
ML1001 – статический LCD GOG (чип в стекле) драйвер для 40-сегментного LCD в позолоченном противоударном исполнении. На них можно каскадно строить цельные из 80 или 120 сегментов LCD индикаторы. Описание драйвера …PIC18 – модуль DMA
Введение Модуль прямого доступа к памяти (DMA) предназначен для обслуживания передачи данных непосредственно между различными областями памяти без вмешательства процессора. Исключив при этом необходимость в интенсивной обработки прерываний процессором, …Сумеречное реле
Реле управления освещением, датчик день-ночь – одним словом фотореле для управления освещением или формирования сигнала для системы умный дом о понижении или повышении освещенности относительно заданного уровня. Реле выполнено по классической схеме, конденсаторный блок питания, от сети переменного тока 220 вольт. …Проект с использованием MCC часть 05
Эту часть назовем так как избавься от delay, там где а это реально не надо. Для это нам потребуется научиться использовать прерывания и работать с таймерами. Что такое таймер? Это …MPLAB® Harmony – или как это просто! Часть 2.
Часть вторая – Первая программа на PIC32. Музыкальная тема к статье, слушаем: Для начала изучения PIC32 надо иметь или демоплату или самому её изготовить имея микроконтроллер. Начнем из трудоемкого варианта …
В записи нет меток.