Yapı dizisini başlatma
Kendimi bir yapı olarak tanımladım:
typedef struct {
unsigned char current;
unsigned char start;
unsigned char target;
unsigned long startTime;
unsigned int duration;
} led;
Bunun gibi bir örneğini başlatabildim:
led h_red = {0,0,255,0,300};
Ancak, onları bir dizide bulundurmaya çalıştığımda:
led leds[LEDS];
leds[0] = {0,0,0,0,0};
leds[1] = {0,0,0,0,0};
leds[2] = {0,0,255,0,300};
Bu hatayı alıyorum
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};
^~~~
Ve burada neyi yanlış yaptığımı bilmiyorum. Değişikliğin tamamını GitHub'da burada görebilirsiniz.
Yanıtlar
led h_red = {0,0,255,0,300};
Burada bir değişken tanımlıyorsunuz ve aynı zamanda ona bir başlangıç değeri veriyorsunuz. Buna başlatma denir .
led leds[LEDS];
Burada bir dizi tanımlıyorsunuz. Global kapsamda olduğundan ve açıkça başlatılmadığından, örtük olarak tüm bayt sıfırına başlatılır.
leds[0] = {0,0,0,0,0};
Burada, dizinin daha önce tanımlanmış bir elemanına bir değer vermeye çalışıyorsunuz. Bu nedenle bu bir başlatma değil , bir atamadır . İlklendirmelerden farklı olarak, atamalar bir işlevin dışında olamaz. Başlangıç değerlerini atamak istiyorsanız, bunu içinde yapabilirsiniz setup()
.
Alternatif olarak, diziyi tanımlarken başlatabilirsiniz:
led leds[LEDS] = {
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 255, 0, 300}
};
@Edgar Bonet'in cevabını yükselttim çünkü doğru.
Yine de birkaç örnek ve açıklama eklemek istiyorum.
Anahtar özet:
C ve C ++ 'da, işlevlerin dışında kod mantığına sahip olamazsınız . İşlevlerin dışındaki genel bağlam, yalnızca bildirimler , tanımlar ve bazı başlatmalar / yapıcılar için tasarlanmıştır. Tüm kod mantığı bir işlevin içinde olmalıdır . Kod mantığı , yapım sonrası değişken atamalarını, if
ifadeleri vb. İçerir .
Örnekler:
1. İzin verilmez:
Bu nedenle, tüm işlev kapsamlarının dışında başlatılmayan atamalar yapmaya çalıştığı için aşağıdakileri YAPAMAZSINIZ .
Ayrıca C ++ 'da (Arduino), typedef
yapılar için de kullanmanız gerekmediğine dikkat edin , bu yüzden bunu struct
tanımdan çıkardım . Ayrıca , bit cinsinden tam tür boyutunu belirttikleri için veri türleri için daha güvenli ve "en iyi uygulama" olarak kabul edilen stdint.h türlerini kullanıyorum . Kullanım uint8_t
yerine unsigned char
, uint32_t
yerine Arduino Uno'nın ait unsigned long
ve uint16_t
yerine Arduino Uno'nın arasında unsigned int
. Ayrıca, değişken sabitleri ayarlamak için özellikle C ++ ' constexprda veya numaralandırmalar tercih edilir #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. İzin verilir:
Bununla birlikte, yapı ile aynı zamanda meydana geldikleri sürece, işlevlerin dışında değişken başlatmalara sahip olabilirsiniz , bu nedenle bu tamamen geçerlidir:
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. Ayrıca izin verilir:
Veya yeniden atamalarınızı aşağıdaki gibi bir işleve taşıyabilirsiniz 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. Bilgisayarda tam, çalıştırılabilir örnek:
İşte yapının içeriğinin değiştirildiğini doğrulamak için yazdırılan bir PC'de eksiksiz, çalıştırılabilir bir örnek:
Çevrimiçi olarak kendiniz çalıştırın: 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;
}
Örnek çıktı:
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
Diğer referanslar:
- https://en.cppreference.com/w/cpp/language/aggregate_initialization
- [cevabım] https://stackoverflow.com/questions/61240589/how-to-initialize-a-struct-to-0-in-c/61240590#61240590