Применение typedef, struct и union

Views: 8904


Полезные описания переменных

Часто необходимо в памяти расположить последовательно разные виды данных, что бы потом можно было их использовать.

Полезные ссылки

Взято и переработано с сайта
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 часть 11Проект с использованием MCC часть 11
    Views: 987 Можно несколько облагородить программу вынести наши процедуры обработки нажатия кнопок в отдельные функции. Но вы должны понимать, что это хоть и не значительно, но будет тормозить общую скорость …
  • Toyota Auto Fader – Модуль включения усилителяToyota Auto Fader – Модуль включения усилителя
    Views: 2075 Toyota Auto Fader – Модуль включения усилителя. Часто автолюбители прибегают к замене штатного головного устройства на универсальное мультимедийное, в котором значительно расширены функциональные возможности. Если возникает желание оставить …
  • JDY-62A Audio bluetooth moduleJDY-62A Audio bluetooth module
    Views: 1853 Простой модуль для простого аудио блютуса. Встроенные подсказки на английском языке. Модуль включён, режим муте – после подачи питания. Контроль разряда батареи предупреждение что батарея разряжена и необходима …
  • MPLAB® Harmony – или как это просто! Часть 1.MPLAB® Harmony – или как это просто! Часть 1.
    Views: 3806 Часть первая – Установка Гармонии. Музыкальная тема к статье, слушаем: В начале запуска нового проекта и выбора микроконтроллера стоит задача правильно его сконфигурировать, прежде чем перейти к реализации …
  • WiFi ESP8266 – AT команды связанные с функцией Wi-FiWiFi ESP8266 – AT команды связанные с функцией Wi-Fi
    Views: 5680 AT команды связанные с функцией Wi-Fi Функции Wi-Fi подключения, запускаться из командной строки Команда Описание  1 AT+CWMODE Проверка, настройка режима работы Wi-Fi (sta/AP/sta+AP), (не рекомендуется для новых проектов). 2 …
  • Analog-to-Digital Converter with Computation Technical BriefAnalog-to-Digital Converter with Computation Technical Brief
    Views: 1441 Аналого-цифровой преобразователь с вычислительным модулем. ВВЕДЕНИЕ Аналого-цифровой преобразователь (ADC) с вычислительным модулем (ADC2) в 8-разрядном микроконтроллере Microchip имеет встроенные вычислительные функции, которые обеспечивают функции пост-обработки, такие как передискретизация, …
  • My libraries for Altium DesignerMy libraries for Altium Designer
    Views: 4321 Attention, this version of the database is outdated today. See updates in articles https://catcatcat.d-lan.dp.ua/altium-designer-my-setup-system-and-project-structure  and https://catcatcat.d-lan.dp.ua/altium-designer-my-setup-system-and-project-structure-v23-2/    My libraries for Altium designer  (Updated V – 29/05/2022) (c) 2021 …
  • Дифференциальный терморегуляторДифференциальный терморегулятор
    Views: 4111 Дифференциальный терморегулятор ch-3020 Назначение. Ch-c3020 представляет собой дифференциальный терморегулятор. Основное назначение солнечные системы горячего водоснабжения, а также вентиляционные системы управление притоком свежего воздуха. Контроллер позволяет работать пяти режимах. …
  • Система AT команд версии V2.0 для ESP8266 и ESP32Система AT команд версии V2.0 для ESP8266 и ESP32
    Views: 13501 Появление нового модуля на базе ESP32 заставило систематизировать систему AT команд, а так же систему обновления и для модулей на базе ESP8266. Начиная с версии v2.0 в ESP8266 …
  • Датчик контроля протечки воды ch-c0020Датчик контроля протечки воды ch-c0020
    Views: 2072 Как здорово летом под теплым дождем с тобою вдвоем оказаться. Как классно по лужам бежать босиком, с тобою играть и смеяться! Но совсем грустно оказаться под таким дождем, который течет с …



Поделись этим!

Catcatcat

catcatcat

Development of embedded systems based on Microchip microcontrollers.

Продолжайте читать

НазадДалее