Menginisialisasi Array dari struct

Dec 20 2020

Saya mendefinisikan diri saya struct:

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

Saya bisa menginisialisasi contoh itu seperti ini:

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

Namun, ketika saya mencoba untuk memilikinya dalam sebuah array:

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

Saya mendapatkan kesalahan ini

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};
 ^~~~

Dan saya tidak tahu apa yang saya lakukan salah di sini. Anda dapat melihat perubahan lengkapnya di sini di GitHub

Jawaban

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

Di sini, Anda mendefinisikan variabel, dan pada saat yang sama memberinya nilai awal. Ini disebut inisialisasi .

led leds[LEDS];

Di sini Anda mendefinisikan sebuah array. Karena berada dalam cakupan global, dan tidak diinisialisasi secara eksplisit, ini secara implisit diinisialisasi ke semua byte nol.

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

Di sini, Anda mencoba memberi nilai pada elemen larik yang sudah ditentukan sebelumnya. Dengan demikian, ini bukan inisialisasi, tetapi tugas . Tidak seperti inisialisasi, tugas tidak boleh ada di luar fungsi. Jika Anda ingin menetapkan nilai awal, Anda dapat melakukannya di setup().

Alternatifnya, Anda dapat menginisialisasi array saat Anda mendefinisikannya:

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

Saya telah memberi suara positif pada jawaban @Edgar Bonet , karena itu benar.

Saya ingin menambahkan beberapa contoh dan penjelasan lagi.

Ringkasan kunci:

Di C dan C ++, Anda TIDAK dapat memiliki logika kode di luar fungsi. Konteks global di luar fungsi dimaksudkan untuk deklarasi , definisi , dan beberapa inisialisasi / konstruktor saja. Semua logika kode harus berada di dalam suatu fungsi . Logika kode mencakup tugas variabel pasca konstruksi, ifpernyataan, dll.

Contoh:

1. TIDAK diizinkan:

Oleh karena itu, Anda TIDAK dapat melakukan hal berikut, karena ini mencoba melakukan tugas non-inisialisasi di luar semua cakupan fungsi.

Perhatikan juga bahwa di C ++ (yang merupakan Arduino), Anda juga tidak perlu menggunakan typedefuntuk struct, jadi saya telah menghapusnya dari structdefinisi. Saya juga menggunakan tipe stdint.h , yang dianggap lebih aman dan "praktik terbaik" untuk tipe data, karena mereka menentukan ukuran tipe yang tepat dalam bit. Gunakan uint8_tsebagai pengganti unsigned char, uint32_tbukan Arduino Uno unsigned long, dan uint16_talih-alih Arduino Uno unsigned int. Selain itu, di C ++ khususnya, constexpratau enum lebih disukai daripada #definemenetapkan konstanta variabel.

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. DIIZINKAN:

Anda BISA, bagaimanapun, memiliki inisialisasi variabel di luar fungsi, selama itu terjadi pada waktu yang sama dengan konstruksi , jadi ini benar-benar valid:

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. Juga diperbolehkan:

Atau, Anda bisa memindahkan penugasan kembali Anda ke suatu fungsi, seperti 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. Contoh lengkap yang dapat dijalankan pada PC:

Berikut adalah contoh lengkap yang dapat dijalankan pada PC, dengan pencetakan untuk memverifikasi bahwa konten struct telah diubah:

Jalankan sendiri secara online: 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;
}

Output sampel:

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

Referensi lain:

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