user71042: I defined myself a struct:
typedef struct {
  unsigned char current;
  unsigned char start;
  unsigned char target;
  unsigned long startTime;
  unsigned int duration;
} led;

I was able to initialize an instance of that like this:
led h_red = {0,0,255,0,300};

However, when I try to have them in an 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};

I get this error
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};
 ^~~~

And I have no idea what I'm doing wrong here. You can see the full change here on GitHub

user7727: I've upvoted @Edgar Bonet's answer, because it is correct.
I want to add some more examples and explanations though.
Key summary:
In C and C++, you can NOT have code logic outside of functions. The global context outside of functions is intended for declarations, definitions, and some initializations/constructors only. All code logic must be inside of a function. Code logic includes post-construction variable assignments, if statements, etc.
Examples:
1. NOT allowed:
Therefore, you can NOT do the following, since it attempts to do non-initializing assignments outside of all function scopes.
Notice also that in C++ (which Arduino is), you don't need to use typedef for structs either, so I've removed that from the struct definition. I'm also using the stdint.h types, which are considered safer and "best practice" for data types, as they specify the exact type size in bits. Use uint8_t in place of unsigned char, uint32_t instead of the Arduino Uno's unsigned long, and uint16_t instead of the Arduino Uno's unsigned int. Also, in C++ in particular, constexpr or enums are preferred over #define to set variable constants.
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. IS allowed:
You CAN, however, have variable initializations outside of functions, so long as they occur at the same time as construction, so this is perfectly 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. Also IS allowed:
Or, you can just move your reassignments into a function, such as 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. Full, runnable example on a PC:
Here's a full, runnable example on a PC, with printing to verify the contents of the struct were changed:
Run it online yourself on OnlineGDB here, or from my eRCaGuy_hello_world repo here: struct_array_initialization.cpp:
#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;
}

Sample output:
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

Other references:

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


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


Here, you are defining a variable, and at the same time giving it an
initial value. This is called an initialization.

led leds[LEDS];


Here you are defining an array. Since it is in global scope, and not
explicitly initialized, it is implicitly initialized to all bytes zero.

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


Here, you are trying to give a value to an element of the array that has
already been defined previously. This is thus not an initialization,
but an assignment. Unlike initializations, assignments cannot exist
outside a function. If you want to assign initial values, you can do it
in setup().
Alternatively, you can initialize the array while you define it:
led leds[LEDS] = {
    {0, 0,   0, 0,   0},
    {0, 0,   0, 0,   0},
    {0, 0, 255, 0, 300}
};


71042: <p>I defined myself a struct:</p>
<pre><code>typedef struct {
  unsigned char current;
  unsigned char start;
  unsigned char target;
  unsigned long startTime;
  unsigned int duration;
} led;
</code></pre>
<p>I was able to initialize an instance of that like this:</p>
<pre><code>led h_red = {0,0,255,0,300};
</code></pre>
<p>However, when I try to have them in an array:</p>
<pre><code>led leds[LEDS];
leds[0] = {0,0,0,0,0};
leds[1] = {0,0,0,0,0};
leds[2] = {0,0,255,0,300};
</code></pre>
<p>I get this error</p>
<pre><code>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};
 ^~~~
</code></pre>
<p>And I have no idea what I'm doing wrong here. You can see the full change <a href="https://github.com/iGEL/c-signal/commit/f27b9fa8ee9325455efe2c99100cbf0b04785257#diff-2cf64226463199d393dbbb66a4d404277bbe98a068de58e26005121d8368ea24R28-R30" rel="nofollow noreferrer">here on GitHub</a></p>
 7727: 
<p>I've upvoted <a href="https://arduino.stackexchange.com/a/80237/7727">@Edgar Bonet's answer</a>, because it is correct.</p>
<p>I want to add some more examples and explanations though.</p>
<h2>Key summary:</h2>
<p>In C and C++, you can NOT have code <em>logic</em> outside of functions. The global context outside of functions is intended for <em>declarations</em>, <em>definitions</em>, and some <em>initializations</em>/<em>constructors</em> only. All code <em>logic</em> must be <em>inside of a function</em>. Code <em>logic</em> includes post-construction variable assignments, <code>if</code> statements, etc.</p>
<h2>Examples:</h2>
<h3>1. NOT allowed:</h3>
<p><strong>Therefore, you can NOT do the following, since it attempts to do non-initializing <em>assignments</em> outside of all function scopes.</strong></p>
<p>Notice also that in C++ (which Arduino is), you don't need to use <code>typedef</code> for structs either, so I've removed that from the <code>struct</code> definition. I'm also using the <a href="http://www.cplusplus.com/reference/cstdint/" rel="nofollow noreferrer">stdint.h types</a>, which are considered safer and &quot;best practice&quot; for data types, as they specify the exact type size in bits. Use <code>uint8_t</code> in place of <code>unsigned char</code>, <code>uint32_t</code> instead of the Arduino Uno's <code>unsigned long</code>, and <code>uint16_t</code> instead of the Arduino Uno's <code>unsigned int</code>. Also, in C++ in particular, <a href="https://en.cppreference.com/w/cpp/language/constexpr" rel="nofollow noreferrer"><code>constexpr</code></a> or enums are preferred over <code>#define</code> to set variable constants.</p>
<pre class="lang-cpp prettyprint-override"><code>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()
{
}
</code></pre>
<h3>2. IS allowed:</h3>
<p><strong>You CAN, however, have variable <em>initializations</em> outside of functions, so long as they occur at the same time as <em>construction</em>, so this is perfectly valid:</strong></p>
<pre class="lang-cpp prettyprint-override"><code>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()
{
}
</code></pre>
<h3>3. Also IS allowed:</h3>
<p><strong>Or, you can just move your reassignments into a function, such as <code>setup()</code>:</strong></p>
<pre class="lang-cpp prettyprint-override"><code>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()
{
}
</code></pre>
<h3>4. Full, runnable example on a PC:</h3>
<p><strong>Here's a full, runnable example on a PC, with printing to verify the contents of the struct were changed:</strong></p>
<p>Run it online yourself <a href="https://onlinegdb.com/MnEOQgCQT" rel="nofollow noreferrer">on OnlineGDB here</a>, or from my <a href="https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world" rel="nofollow noreferrer">eRCaGuy_hello_world</a> repo here: <a href="https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/cpp/struct_array_initialization.cpp" rel="nofollow noreferrer">struct_array_initialization.cpp</a>:</p>
<pre class="lang-cpp prettyprint-override"><code>#include &lt;stdint.h&gt;
#include &lt;stdio.h&gt;

// 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 &lt; ledArrayLen; i++)
    {
        printf(&quot;ledArrayIn[%lu]\n&quot;
               &quot;current   = %u\n&quot;
               &quot;start     = %u\n&quot;
               &quot;target    = %u\n&quot;
               &quot;startTime = %u\n&quot; 
               &quot;duration  = %u\n\n&quot;,
               i,
               ledArrayIn[i].current,
               ledArrayIn[i].start,
               ledArrayIn[i].target,
               ledArrayIn[i].startTime,
               ledArrayIn[i].duration);
    }
}

int main()
{
    printf(&quot;Hello World\n\n&quot;);

    printLeds(leds, ARRAY_LEN(leds));
    
    printf(&quot;==============\n\n&quot;);
    
    // 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;
}
</code></pre>
<p>Sample output:</p>
<pre class="lang-cpp prettyprint-override"><code>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
</code></pre>
<h2>Other references:</h2>
<ol>
<li><a href="https://en.cppreference.com/w/cpp/language/aggregate_initialization" rel="nofollow noreferrer">https://en.cppreference.com/w/cpp/language/aggregate_initialization</a></li>
<li>[my answer] <a href="https://stackoverflow.com/questions/61240589/how-to-initialize-a-struct-to-0-in-c/61240590#61240590">https://stackoverflow.com/questions/61240589/how-to-initialize-a-struct-to-0-in-c/61240590#61240590</a></li>
</ol>
 7508: <blockquote>
<pre class="lang-cpp prettyprint-override"><code>led h_red = {0,0,255,0,300};
</code></pre>
</blockquote>
<p>Here, you are defining a variable, and at the same time giving it an
initial value. This is called an <em>initialization</em>.</p>
<blockquote>
<pre class="lang-cpp prettyprint-override"><code>led leds[LEDS];
</code></pre>
</blockquote>
<p>Here you are defining an array. Since it is in global scope, and not
explicitly initialized, it is implicitly initialized to all bytes zero.</p>
<blockquote>
<pre class="lang-cpp prettyprint-override"><code>leds[0] = {0,0,0,0,0};
</code></pre>
</blockquote>
<p>Here, you are trying to give a value to an element of the array that has
already been defined previously. This is thus <em>not</em> an initialization,
but an <em>assignment</em>. Unlike initializations, assignments cannot exist
outside a function. If you want to assign initial values, you can do it
in <code>setup()</code>.</p>
<p>Alternatively, you can initialize the array while you define it:</p>
<pre class="lang-cpp prettyprint-override"><code>led leds[LEDS] = {
    {0, 0,   0, 0,   0},
    {0, 0,   0, 0,   0},
    {0, 0, 255, 0, 300}
};
</code></pre>
