Инициализация массива структур
Я определил себе структуру:
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
@iGEL, 👍4
2 ответа
Лучший ответ:
led h_red = {0,0,255,0,300};
Здесь вы определяете переменную и в то же время даете ей начальное значение. Это называется инициализацией.
led leds[LEDS];
Здесь вы определяете массив. Поскольку он находится в глобальной области видимости и явно не инициализирован, он неявно инициализируется всеми нулевыми байтами.
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}
};
Я поддержал ответ @Edgar Bonet, потому что он правильный.
Однако я хочу добавить еще несколько примеров и объяснений.
Ключевое резюме:
В C и C ++ вы НЕ можете иметь логику кода вне функций. Глобальный контекст вне функций предназначен только для объявлений, определенийи некоторых инициализаций/конструкторов. Вся логика кода должна быть внутри функции. Логика кода включает в себя назначения переменных после построения, операторы if и т. Д.
Примеры:
1. НЕ допускается:
Поэтому вы НЕ можете сделать следующее, так как он пытается выполнять неинициализирующие назначения за пределами всех областей функций.
Обратите внимание также, что в C ++ (которым является Arduino) вам также не нужно использовать typedef
для структур, поэтому я удалил это из определения структуры
. Я также использую типы stdint.h, которые считаются более безопасными и "лучшими практиками" для типов данных, поскольку они указывают точный размер типа в битах. Используйте uint8_t
вместо unsigned char
, uint32_t
вместо unsigned long Arduino Uno
и uint16_t
вместо unsigned int Arduino Uno
. Кроме того, в частности, в 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: Присвоения переменных (re) НЕ допускаются вне функций в
// C и 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];
// Эта форма агрегатной инициализации во время построения просто прекрасна в
// глобальной области вне всех функций.
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()
{
// Это назначение переменной (re) просто отлично, так как она находится внутри
// функции.
leds[0] = {0, 0, 0, 0, 0};
leds[1] = {0, 0, 0, 0, 0};
leds[2] = {0, 0, 255, 0, 300};
}
void loop()
{
}
4. Полный, выполнимый пример на ПК:
Вот полный, выполняемый пример на ПК с печатью, чтобы убедиться, что содержимое структуры было изменено:
Запустите его онлайн самостоятельно: https://onlinegdb.com/MnEOQgCQT.
#include <stdint.h>
#include <stdio.h>
// Получить количество элементов в массиве C-стиля
#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;
};
// Инициализировать один раз при построении. Эта форма агрегатной инициализации
// может использоваться в любом месте: как внутри, так и снаружи.
Led leds[NUM_LEDS] = {
{ 1, 2, 3, 4, 5},
{ 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15},
};
// Печать полного содержимого массива структур `Led`
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");
// Сделайте это, чтобы установить или изменить структуры в любое время ПОСЛЕ построения!
// Это присвоение переменной (re) разрешено только внутри функции, А НЕ
// в глобальной области вне всех функций!
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
Другие ссылки:
- https://en.cppreference.com/w/cpp/language/aggregate_initialization
- [мой ответ] https://stackoverflow.com/questions/61240589/how-to-initialize-a-struct-to-0-in-c/61240590#61240590
Что касается первого абзаца вашего ответа; Что означает "Я проголосовал за ответ @Edgar Bonet, потому что он правильный". это имеет отношение к вопросу?, @VE7JRO
- Как получить размер (sizeof) массива структур
- Почему структура переменного размера не компилируется в Arduino IDE?
- Создание массива структур, в которых хранятся растровые изображения для работы с u8glib.
- Проблема инициализации массива struct
- Интерпретатор и обработчик сообщений – как сохранить имя функции в структуре?
- Какие накладные расходы и другие соображения существуют при использовании структуры по сравнению с классом?
- Возможно ли иметь массив массивов int?
- Замена нескольких выводов pinMode() и digitalWrite() на массив
Это ключевая часть, на которую следует обратить внимание: ** В отличие от инициализации, назначения не могут существовать вне функции. Если вы хотите присвоить начальные значения, вы можете сделать это в
setup()
.** Вызов OPleds[0] = {0,0,0,0,0};
вполне допустим в другой функции, такой какsetup()
, но НЕ разрешен за пределами всех областей функций, где может иметь место только инициализация. ОП случайно пытался выполнить это назначение в глобальной области, где новые назначения и обычный логический код не допускаются., @Gabriel Staples