Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial Internet of Things >> Ingebed

Union in C Language voor het in- en uitpakken van gegevens

Meer informatie over het in- en uitpakken van gegevens met vakbonden in C-taal.

Meer informatie over het in- en uitpakken van gegevens met vakbonden in C-taal.

In een vorig artikel bespraken we dat de oorspronkelijke toepassing van vakbonden het creëren van een gedeeld geheugengebied was voor elkaar uitsluitende variabelen. In de loop van de tijd hebben de programmeurs vakbonden echter op grote schaal gebruikt voor een heel andere toepassing:het extraheren van kleinere delen van gegevens uit een groter gegevensobject. In dit artikel gaan we dieper in op deze specifieke toepassing van vakbonden.

Verbindingen gebruiken voor het in-/uitpakken van gegevens

De leden van een vakbond worden opgeslagen in een gedeelde geheugenruimte. Dit is de belangrijkste functie waarmee we interessante toepassingen voor vakbonden kunnen vinden.

Beschouw de vakbond hieronder:

unie { uint16_t woord; struct { uint8_t byte1; uint8_t byte2; };} u1; 

Er zijn twee leden binnen deze unie:het eerste lid, "woord", is een variabele van twee bytes. Het tweede lid is een structuur van twee variabelen van één byte. De twee bytes die voor de vakbond zijn toegewezen, worden gedeeld tussen de twee leden.

De toegewezen geheugenruimte kan zijn zoals weergegeven in Afbeelding 1 hieronder.

Figuur 1

Terwijl de variabele "woord" verwijst naar de volledige toegewezen geheugenruimte, verwijzen de variabelen "byte1" en "byte2" naar de gebieden van één byte die de variabele "woord" construeren. Hoe kunnen we deze functie gebruiken? Stel dat u twee variabelen van één byte hebt, "x" en "y", die moeten worden gecombineerd om een ​​enkele variabele van twee bytes te produceren.

In dit geval kunt u de bovenstaande unie gebruiken en "x" en "y" als volgt toewijzen aan de structuurleden:

u1.byte1 =y;u1.byte2 =x; 

Nu kunnen we het 'woord'-lid van de vakbond lezen om een ​​variabele van twee bytes te krijgen die is samengesteld uit 'x'- en 'y'-variabelen (zie afbeelding 2).

Figuur 2

Het bovenstaande voorbeeld toont het gebruik van vakbonden voor het inpakken van twee variabelen van één byte in een enkele variabele van twee byte. We zouden ook het omgekeerde kunnen doen:schrijf een waarde van twee bytes naar "word" en pak deze uit in twee variabelen van één byte door de variabelen "x" en "y" te lezen. Het schrijven van een waarde aan een lid van een vakbond en het lezen van een ander lid ervan wordt soms "data punning" genoemd.

De processor-endianheid

Bij het gebruik van vakbonden voor het in- en uitpakken van gegevens, moeten we voorzichtig zijn met de processor-endianness. Zoals besproken in het artikel van Robert Keim over endianness, specificeert deze term de volgorde waarin de bytes van een data-object in het geheugen worden opgeslagen. Een processor kan little endian of big endian zijn. Met een big-endian processor worden gegevens zo opgeslagen dat de byte met de meest significante bit het laagste geheugenadres heeft. In little-endian-systemen wordt eerst de byte met het minst significante bit opgeslagen.

Het voorbeeld afgebeeld in figuur 3 illustreert de little endian en big endian opslag van de reeks 0x01020304.

Figuur 3. Afbeelding met dank aan IAR.

Laten we de volgende code gebruiken om te experimenteren met de vereniging van de vorige sectie:

#include <stdio.h>#include <stdint.h>int main(){ union { struct{ uint8_t byte1; uint8_t byte2; }; uint16_t woord; } u1; u1.byte1 =0x21;u1.byte2 =0x43; printf("Woord is:%#X", u1.word);return 0;} 

Als ik deze code uitvoer, krijg ik de volgende uitvoer:

Woord is:0X4321

Dit toont aan dat de eerste byte van de gedeelde geheugenruimte (“u1.byte1”) wordt gebruikt om de minst significante byte (0X21) van de variabele “word” op te slaan. Met andere woorden, de processor die ik gebruik om de code uit te voeren is little endian.

Zoals u kunt zien, kan deze specifieke toepassing van vakbonden implementatieafhankelijk gedrag vertonen. Dit zou echter geen serieus probleem moeten zijn, want voor dergelijke codering op laag niveau kennen we meestal de endianness van de processor. Als we deze details niet weten, kunnen we de bovenstaande code gebruiken om erachter te komen hoe de gegevens in het geheugen zijn georganiseerd.

Alternatieve oplossing

In plaats van vakbonden te gebruiken, kunnen we ook de bitsgewijze operatoren gebruiken om gegevens in of uit te pakken. We kunnen bijvoorbeeld de volgende code gebruiken om twee variabelen van één byte, "byte3" en "byte4", te combineren en een enkele variabele van twee bytes ("word2") te produceren:

word2 =(((uint16_t) byte3) <<8 ) | ((uint16_t) byte4); 

Laten we de output van deze twee oplossingen vergelijken in de gevallen van little endian en big endian. Bekijk de onderstaande code:

#include <stdio.h>#include <stdint.h>int main(){union { struct { uint8_t byte1; uint8_t byte2; }; uint16_t woord1; } u1; u1.byte1 =0x21;u1.byte2 =0x43;printf("Woord1 is:%#X\n", u1.word1); uint8_t byte3, byte4;uint16_t woord2;byte3 =0x21;byte4 =0x43;word2 =(((uint16_t) byte3) <<8 ) | ((uint16_t) byte4);printf("Woord2 is:%#X \n", woord2); retourneer 0;} 

Als we deze code compileren voor een big endian-processor zoals TMS470MF03107 , de uitvoer zal zijn:

Woord1 is:0X2143

Woord2 is:0X2143

Als we het echter compileren voor een kleine endian-processor zoals STM32F407IE , de uitvoer zal zijn:

Woord1 is:0X4321

Woord2 is:0X2143

Terwijl de op unie gebaseerde methode hardwareafhankelijk gedrag vertoont, leidt de methode gebaseerd op de shift-bewerking tot hetzelfde resultaat, ongeacht de processor-endianness. Dit komt door het feit dat we bij de laatste benadering een waarde toewijzen aan de naam van een variabele ("word2") en de compiler zorgt voor de geheugenorganisatie die door het apparaat wordt gebruikt. Met de op union gebaseerde methode veranderen we echter de waarde van de bytes die de variabele "word1" construeren.

Hoewel de op unie gebaseerde methode hardwareafhankelijk gedrag vertoont, heeft het het voordeel dat het beter leesbaar en onderhoudbaar is. Daarom gebruiken veel programmeurs bij voorkeur vakbonden voor deze toepassing.

Een praktisch voorbeeld van "Data Punning"

Wanneer we werken met gangbare seriële communicatieprotocollen, moeten we mogelijk gegevens in- of uitpakken. Overweeg een serieel communicatieprotocol dat tijdens elke communicatiereeks één byte aan gegevens verzendt/ontvangt. Zolang we met variabelen van één byte werken, is het gemakkelijk om de gegevens over te dragen, maar wat als we een structuur van willekeurige grootte hebben die via de communicatielink zou moeten gaan? In dit geval moeten we ons gegevensobject op de een of andere manier voorstellen als een array van variabelen van één byte lang. Zodra we deze array-of-bytes-representatie hebben gekregen, kunnen we de bytes overdragen via de communicatielink. Vervolgens kunnen we ze aan de ontvangerzijde op de juiste manier inpakken en de originele structuur opnieuw opbouwen.

Stel bijvoorbeeld dat we een float-variabele, "f1", moeten verzenden via de UART-communicatie. Een float-variabele neemt meestal vier bytes in beslag. Daarom kunnen we de volgende unie gebruiken als buffer voor het extraheren van de vier bytes van "f1":

union { float f; struct { uint8_t byte [4]; };} u1; 

De zender schrijft de variabele "f1" naar het vlotterlid van de vakbond. Vervolgens leest het de "byte" -array en stuurt de bytes langs de communicatielink. De ontvanger doet het omgekeerde:hij schrijft de ontvangen gegevens naar de "byte" -array van zijn eigen unie en leest de variabele float van de unie als de ontvangen waarde. We zouden deze techniek kunnen toepassen om een ​​gegevensobject van willekeurige grootte over te dragen. De volgende code kan een eenvoudige test zijn om deze techniek te verifiëren.

#include <stdio.h>#include <stdint.h>int main(){float f1=5.5; unie buffer { float f; struct { uint8_t byte [4]; }; }; uniebuffer buff_Tx;unionbuffer buff_Rx;buff_Tx.f =f1;buff_Rx.byte[0] =buff_Tx.byte[0];buff_Rx.byte[1] =buff_Tx.byte[1];buff_Rx.byte[2] =buff_Tx .byte[2];buff_Rx.byte[3] =buff_Tx.byte[3]; printf("De ontvangen gegevens zijn:%f", buff_Rx.f); retourneer 0;} 

Figuur 4 hieronder visualiseert de besproken techniek. Merk op dat de bytes opeenvolgend worden overgedragen.

Figuur 4

Conclusie

Terwijl de oorspronkelijke toepassing van vakbonden het creëren van een gedeeld geheugengebied voor elkaar uitsluitende variabelen was, hebben de programmeurs in de loop van de tijd op grote schaal gebruik gemaakt van vakbonden voor een geheel andere toepassing:het gebruik van vakbonden voor het in- en uitpakken van gegevens. Deze specifieke toepassing van vakbonden omvat het schrijven van een waarde aan een lid van de vakbond en het lezen van een ander lid ervan.

"Data punning" of het gebruik van vakbonden voor het in-/uitpakken van gegevens kan leiden tot hardware-afhankelijk gedrag. Het heeft echter het voordeel dat het beter leesbaar en onderhoudbaar is. Dat is de reden waarom veel programmeurs de voorkeur geven aan vakbonden voor deze toepassing. "Data punning" kan met name handig zijn als we een gegevensobject van willekeurige grootte hebben dat via een seriële communicatieverbinding moet gaan.

Ga naar deze pagina om een ​​volledige lijst van mijn artikelen te zien.


Ingebed

  1. Applicatieprestaties beter maken voor gebruikers en klanten bij CyrusOne
  2. Semaphores:nutsvoorzieningen en datastructuren
  3. De strategie en oplossingen van het leger voor op conditie gebaseerd onderhoud
  4. De voordelen van het aanpassen van IIoT- en data-analyseoplossingen voor EHS
  5. Verantwoorde en betrouwbare AI bouwen
  6. Wat is fog computing en wat betekent het voor IoT?
  7. C - Vakbonden
  8. Waarom gegevens en context essentieel zijn voor de zichtbaarheid van de toeleveringsketen
  9. Voor wagenparkbeheer zijn AI en IoT beter samen
  10. Industrial AIoT:combinatie van kunstmatige intelligentie en IoT voor industrie 4.0
  11. Litmus en Oden Fuse IIoT-oplossingen voor slimme productie