구조체 배열 초기화

Dec 20 2020

나는 스스로 구조체를 정의했다.

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

다음과 같이 인스턴스를 초기화 할 수있었습니다.

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

그러나 배열에 넣으려고 할 때 :

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

이 오류가 발생합니다.

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

그리고 나는 내가 여기서 뭘 잘못하고 있는지 전혀 모른다. 여기 GitHub 에서 전체 변경 사항을 확인할 수 있습니다.

답변

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

여기에서 변수를 정의하고 동시에 초기 값을 제공합니다. 이것을 초기화 라고합니다 .

led leds[LEDS];

여기에서 배열을 정의합니다. 전역 범위에 있고 명시 적으로 초기화되지 않았기 때문에 암시 적으로 모든 바이트 0으로 초기화됩니다.

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

여기에서 이전에 이미 정의 된 배열의 요소에 값을 제공하려고합니다. 이 때문에입니다 하지 초기화하지만 할당 . 초기화와 달리 할당은 함수 외부에 존재할 수 없습니다. 초기 값을 할당하려면에서 할 수 있습니다 setup().

또는 정의하는 동안 배열을 초기화 할 수 있습니다.

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

@Edgar Bonet의 답변 이 정확하기 때문에 upvoted 했습니다.

그래도 몇 가지 예와 설명을 추가하고 싶습니다.

주요 요약 :

C 및 C ++에서는 함수 외부에 코드 논리를 가질 수 없습니다 . 함수 외부의 전역 컨텍스트는 선언 , 정의 및 일부 초기화 / 생성자 전용입니다. 모든 코드 논리함수 내에 있어야합니다 . 코드 로직 에는 사후 구성 변수 할당, if문 등이 포함됩니다.

예 :

1. 허용되지 않음 :

따라서 모든 함수 범위 외부에서 초기화되지 않는 할당을 시도하기 때문에 다음을 수행 할 수 없습니다 .

또한 C ++ (Arduino)에서는 typedef구조체에도 사용할 필요가 없으므로 struct정의 에서 제거했습니다 . 또한 정확한 유형 크기를 비트 단위로 지정하므로 데이터 유형에 대해 더 안전하고 "모범 사례"로 간주되는 stdint.h 유형을 사용하고 있습니다 . 사용 uint8_t대신에 unsigned char, uint32_t대신 아두 이노 우노의의 unsigned long, 그리고 uint16_t대신 아두 이노 우노의의 unsigned int. 또한 특히 C ++에서는 변수 상수를 설정 constexpr하는 것보다 열거 형이 선호 #define됩니다.

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. 허용 :

그러나 구성 과 동시에 발생하는 한 함수 외부에서 변수 초기화를 가질 수 있으므로 이것은 완벽하게 유효합니다.

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. 허용 :

또는 다음과 같은 기능으로 재 할당을 이동할 수 있습니다 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. PC에서 실행 가능한 전체 예제 :

다음은 구조체의 내용이 변경되었는지 확인하기 위해 인쇄하여 PC에서 실행 가능한 전체 예제입니다.

온라인으로 직접 실행하십시오. 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;
}

샘플 출력 :

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

기타 참조 :

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