Array von Strukturen initialisieren

Dec 20 2020

Ich habe mir eine Struktur definiert:

typedef struct {
  unsigned char current;
  unsigned char start;
  unsigned char target;
  unsigned long startTime;
  unsigned int duration;
} led;

Ich konnte eine Instanz davon wie folgt initialisieren:

led h_red = {0,0,255,0,300};

Wenn ich jedoch versuche, sie in einem Array zu haben:

led leds[LEDS];
leds[0] = {0,0,0,0,0};
leds[1] = {0,0,0,0,0};
leds[2] = {0,0,255,0,300};

Ich bekomme diesen Fehler

signal:28:1: error: 'leds' does not name a type
 leds[0] = {0,0,0,0,0};
 ^~~~
signal:29:1: error: 'leds' does not name a type
 leds[1] = {0,0,0,0,0};
 ^~~~
signal:30:1: error: 'leds' does not name a type
 leds[2] = {0,0,255,0,300};
 ^~~~

Und ich habe keine Ahnung, was ich hier falsch mache. Sie können die vollständige Änderung hier auf GitHub sehen

Antworten

8 EdgarBonet Dec 20 2020 at 21:17
led h_red = {0,0,255,0,300};

Hier definieren Sie eine Variable und geben ihr gleichzeitig einen Anfangswert. Dies wird als Initialisierung bezeichnet .

led leds[LEDS];

Hier definieren Sie ein Array. Da es sich im globalen Bereich befindet und nicht explizit initialisiert wird, wird es implizit auf alle Bytes Null initialisiert.

leds[0] = {0,0,0,0,0};

Hier versuchen Sie, einem Element des Arrays, das bereits zuvor definiert wurde, einen Wert zuzuweisen. Dies ist also keine Initialisierung, sondern eine Zuordnung . Im Gegensatz zu Initialisierungen können Zuweisungen nicht außerhalb einer Funktion vorhanden sein. Wenn Sie Anfangswerte zuweisen möchten, können Sie dies in tun setup().

Alternativ können Sie das Array initialisieren, während Sie es definieren:

led leds[LEDS] = {
    {0, 0,   0, 0,   0},
    {0, 0,   0, 0,   0},
    {0, 0, 255, 0, 300}
};
GabrielStaples Dec 23 2020 at 04:18

Ich habe die Antwort von @Edgar Bonet positiv bewertet , weil sie richtig ist.

Ich möchte jedoch noch einige Beispiele und Erklärungen hinzufügen.

Schlüsselübersicht:

In C und C ++ können Sie KEINE Codelogik außerhalb von Funktionen haben. Der globale Kontext außerhalb von Funktionen ist nur für Deklarationen , Definitionen und einige Initialisierungen / Konstruktoren vorgesehen . Die gesamte Codelogik muss sich innerhalb einer Funktion befinden . Die Codelogik umfasst Zuweisungen, ifAnweisungen usw. für Variablen nach dem Aufbau .

Beispiele:

1. NICHT erlaubt:

Daher können Sie Folgendes NICHT ausführen, da versucht wird, Zuweisungen außerhalb aller Funktionsbereiche nicht zu initialisieren .

Beachten Sie auch, dass Sie in C ++ (welches Arduino ist) auch nicht typedeffür Strukturen verwenden müssen, also habe ich das aus der structDefinition entfernt. Ich verwende auch die Typen stdint.h , die als sicherer und "Best Practice" für Datentypen gelten, da sie die genaue Typgröße in Bit angeben. Verwenden Sie uint8_tanstelle von unsigned char, uint32_tanstelle des Arduino Uno unsigned long, und uint16_tanstelle des Arduino Uno unsigned int. Insbesondere in C ++ werden auch constexprAufzählungen dem Festlegen #definevariabler Konstanten vorgezogen .

constexpr uint8_t NUM_LEDS = 3;

struct Led {
  uint8_t current;
  uint8_t start;
  uint8_t target;
  uint32_t startTime;
  uint16_t duration;
};

Led leds[NUM_LEDS];
// NOT OK: Variable (re)assignments are NOT allowed outside of functions in 
// C and C++.
leds[0] = {0, 0,   0, 0,   0};
leds[1] = {0, 0,   0, 0,   0};
leds[2] = {0, 0, 255, 0, 300};

void setup()
{
}

void loop()
{
}

2. IST erlaubt:

Sie KÖNNEN jedoch variable Initialisierungen außerhalb von Funktionen haben, solange diese gleichzeitig mit der Konstruktion auftreten . Dies ist also vollkommen gültig:

Led leds[NUM_LEDS];
// This form of aggregate initialization during construction is just fine in the 
// global scope outside of all functions. 
Led leds[NUM_LEDS] = {
    {0, 0,   0, 0,   0},
    {0, 0,   0, 0,   0},
    {0, 0, 255, 0, 300},
};

void setup()
{
}

void loop()
{
}

3. Auch ist erlaubt:

Sie können Ihre Neuzuweisungen auch einfach in eine Funktion verschieben, z. B setup().:

Led leds[NUM_LEDS];

void setup()
{
    // This variable (re)assignment is just fine since it's inside 
    // of a function.
    leds[0] = {0, 0,   0, 0,   0};
    leds[1] = {0, 0,   0, 0,   0};
    leds[2] = {0, 0, 255, 0, 300};
}

void loop()
{
}

4. Vollständiges, ausführbares Beispiel auf einem PC:

Hier ist ein vollständiges, ausführbares Beispiel auf einem PC, bei dem gedruckt wird, um zu überprüfen, ob der Inhalt der Struktur geändert wurde:

Führen Sie es selbst online aus: https://onlinegdb.com/MnEOQgCQT.

#include <stdint.h>
#include <stdio.h>

// Get the number of elements in a C-style array 
#define ARRAY_LEN(array) (sizeof(array)/sizeof(array[0]))

constexpr uint8_t NUM_LEDS = 3;

struct Led {
  uint8_t current;
  uint8_t start;
  uint8_t target;
  uint32_t startTime;
  uint16_t duration;
};

// To initialize once at construction. This form of aggregate initialization 
// can be used anywhere: both inside and outside functions. 
Led leds[NUM_LEDS] = {
    { 1,  2,  3,  4,  5},
    { 6,  7,  8,  9, 10},
    {11, 12, 13, 14, 15},
};

// Print the full contents of an array of `Led` structs
void printLeds(const Led ledArrayIn[], size_t ledArrayLen)
{
    for (size_t i = 0; i < ledArrayLen; i++)
    {
        printf("ledArrayIn[%lu]\n"
               "current   = %u\n"
               "start     = %u\n"
               "target    = %u\n"
               "startTime = %u\n" 
               "duration  = %u\n\n",
               i,
               ledArrayIn[i].current,
               ledArrayIn[i].start,
               ledArrayIn[i].target,
               ledArrayIn[i].startTime,
               ledArrayIn[i].duration);
    }
}

int main()
{
    printf("Hello World\n\n");

    printLeds(leds, ARRAY_LEN(leds));
    
    printf("==============\n\n");
    
    // Do this to set or change the structs at any time AFTER construction!
    // This variable (re)assignment is only allowed inside of a function, NOT 
    // in the global scope outside of all functions!
    leds[0] = {10, 20,  30,  40,  50};
    leds[1] = {60, 70,  80,  90, 100};
    leds[2] = { 0,  0, 255,   0, 300};
    
    printLeds(leds, ARRAY_LEN(leds));

    return 0;
}

Beispielausgabe:

Hello World

ledArrayIn[0]
current   = 1
start     = 2
target    = 3
startTime = 4
duration  = 5

ledArrayIn[1]
current   = 6
start     = 7
target    = 8
startTime = 9
duration  = 10

ledArrayIn[2]
current   = 11
start     = 12
target    = 13
startTime = 14
duration  = 15

==============

ledArrayIn[0]
current   = 10
start     = 20
target    = 30
startTime = 40
duration  = 50

ledArrayIn[1]
current   = 60
start     = 70
target    = 80
startTime = 90
duration  = 100

ledArrayIn[2]
current   = 0
start     = 0
target    = 255
startTime = 0
duration  = 300

Weitere Referenzen:

  1. https://en.cppreference.com/w/cpp/language/aggregate_initialization
  2. [meine Antwort] https://stackoverflow.com/questions/61240589/how-to-initialize-a-struct-to-0-in-c/61240590#61240590