Eingebettete C-Strukturen: Praktischer Leitfaden zu Definition, Nutzung und Speicheroptimierung
Strukturen sind ein Eckpfeiler effizienter eingebetteter C-Programmierung. In diesem Artikel untersuchen wir ihre praktischen Anwendungen, die Syntax für ihre Deklaration und die Auswirkungen der Datenausrichtung auf die Speichernutzung. Durch strategische Anordnung der Strukturmitglieder können Sie den Footprint Ihrer Datenobjekte oft reduzieren – eine kritische Überlegung in ressourcenbeschränkten Umgebungen.
Dieser Artikel bietet einen prägnanten, aber umfassenden Überblick über Strukturen in eingebettetem C. Wir behandeln ihre realen Anwendungen, wie man sie korrekt deklariert und die subtilen Regeln der Datenausrichtung, die die Größe Ihrer Strukturen beeinflussen.
Strukturen
Wenn mehrere Variablen desselben Typs eine logische Beziehung teilen, ist ein Array eine praktische Gruppierung. Um beispielsweise die letzten 50 Samples von einem ADC zu speichern, der eine Spracheingabe digitalisiert, könnten Sie verwenden:
uint16_t voice[50];
Hier ist uint16_t ein vorzeichenloses 16-Bit-Integer, definiert in stdint.h, was konsistente Größe über Plattformen hinweg gewährleistet.
Was aber, wenn Sie Variablen verschiedener Typen gruppieren müssen – sagen wir, ein Array von Samples und die Abtastrate des ADC? Sie separat als unabhängige Variablen zu deklarieren, erzeugt unnötigen Overhead. Stattdessen können Sie sie in einer Struktur kapseln:
struct record { uint16_t voice[50]; float sample_rate; };
Die record-Struktur enthält nun sowohl ein Array von uint16_t als auch einen float in einem einzelnen, logisch verbundenen Datenobjekt.
Warum sind Strukturen wichtig?
Strukturen ermöglichen es Ihnen, heterogene Variablen in eine zusammenhängende Einheit zu assoziieren, was die Manipulation vereinfacht und die Lesbarkeit verbessert. Sie bilden die Basis komplexerer Datenstrukturen wie verketteter Listen und Nachrichtenpuffer, die in eingebetteter Kommunikation und Sensordatenverarbeitung allgegenwärtig sind.
Beispielsweise werden memory-mapped Peripherien auf Mikrocontrollern oft als Strukturen dargestellt, die das Hardware-Register-Layout spiegeln, was einen direkten Registerzugriff über Membersyntax ermöglicht.

Abbildung 1. Strukturen können zur Implementierung einer verketteten Liste verwendet werden.

Abbildung 2. Speicherabbild eines STM32 MCU. Bild mit freundlicher Genehmigung von Embedded Systems with ARM.
Deklaration einer Struktur
Zuerst definieren Sie ein Struktur-Template. Betrachten Sie dieses Beispiel:
struct record { uint16_t voice[4]; float sample_rate; };
Das Template selbst verbraucht keinen Speicher; Allokation erfolgt erst, wenn Sie eine Variable dieses Typs deklarieren:
struct record mic1;
Jetzt belegt mic1 genug Platz für vier uint16_t-Elemente und einen float. Greifen Sie über den Punktoperator auf Mitglieder zu:
mic1.voice[0] = 100; float fs = mic1.sample_rate;
Andere Wege zur Deklaration einer Struktur
Während das gängigste Muster die Struktur zuerst definiert und dann Variablen deklariert, bietet C alternative Syntaxen:
Syntax 1: Tag und Variable zusammen
struct record { uint16_t voice[4]; float sample_rate; } mic1;
Nachfolgende Variablen können separat deklariert werden:
struct record mic2;
Syntax 2: Anonymes Template
struct { uint16_t voice[4]; float sample_rate; } mic1;
Hier können Sie das Template nicht wiederverwenden, da es keinen Namen hat.
Syntax 3: Anonyme verschachtelte Struktur
struct test { struct { float f; char a; }; } test_var;
Greifen Sie direkt auf die inneren Mitglieder zu:
test_var.f = 1.2f;
Anonyme Strukturen reduzieren Verbosität, sollten aber um der Klarheit willen judicious eingesetzt werden.
Speicherlayout für eine Struktur
Der C-Standard garantiert, dass Mitglieder sequenziell im Speicher angeordnet sind, in der Reihenfolge der Deklaration. Zum Beispiel:
struct Test2 { uint8_t c; uint32_t d; uint8_t e; uint16_t f; } MyStruct;
Auf einer 32-Bit-Maschine beträgt sizeof(MyStruct) 12 Bytes aufgrund von Padding, das uint32_t an eine 4-Byte-Grenze ausrichtet. Eine Neuanordnung der Mitglieder kann Padding eliminieren:
struct Test2 { uint32_t d; uint16_t f; uint8_t c; uint8_t e; } MyStruct;
Jetzt sinkt sizeof(MyStruct) auf 8 Bytes – wertvolle Einsparungen in speicherbeschränkter Firmware.

Abbildung 3. Datenausrichtung kann Padding zum Speicherlayout einer Struktur hinzufügen.
Zusammenfassung
- Strukturen lassen Sie heterogene Variablen in eine einzelne, handhabbare Einheit bündeln, was Code-Klarheit und Effizienz verbessert.
- Benutzerdefinierte Datenstrukturen unterstützen Aufgaben wie Geräte-zu-Geräte-Messaging und Sensordaten-Speicherung.
- Sie sind essenziell für das Mapping von Hardware-Registern in memory-mapped Peripherien.
- Neuordnung der Mitglieder zur Berücksichtigung der Ausrichtung kann die Strukturgröße signifikant reduzieren.
Entdecken Sie mehr unserer eingebetteten C-Tutorials hier.
Eingebettet
- Was sind Refraktärmetalle? Expertenüberblick über Eigenschaften und Anwendungen
- Terrassenschrauben (Deck Screws) erklärt: Typen, Vorteile & Vergleich zu Holzschrauben
- Federbeaufschlagte Dichtungen (Spring-Energized Seals): Design, Funktion und industrielle Vorteile
- Holzschrauben erklärt: Typen, Eigenschaften und Auswahl-Tipps
- Stahllegierungen erklärt: Typen, Zusammensetzung und Anwendungen
- Daten im Internet of Reliability nutzen: Strategien für effektives Management
- Java Datenstrukturen: Kernklassen & Collections Framework erkunden
- Industrial Internet of Things (IIoT): Definition, Umfang und industrielle Auswirkungen
- Instandhaltungsdaten erklärt: Der Schlüssel zu zuverlässigem Asset-Management
- Modernes Holzhandwerk: Trends, Technologien & Techniken im Überblick