It looks like you're not allocating space for your states in the machine past the first one.

StateMachine * create_state_machine(const char* name) {
  StateMachine * temp;

  temp = malloc(sizeof(struct StateMachine));

  if (temp == NULL) {
    exit(127);
  }

  temp->name = name;
  temp->total_states = 0;

  temp->states = malloc(sizeof(struct State)); // This bit here only allocates space for 1.
  return temp;
}

You're probably better off putting an array of states of fixed size in the state machine struct. If that's not okay, you'll have to realloc and move the whole set around or allocate chunks and keep track of the current length, or make a linked list.

Incidentally, init, foo, and bar never get used.

Edit: What I'm suggesting looks like this:

#define MAX_STATES 128 // Pick something sensible.
typedef struct StateMachine {
  const char * name;
  int total_states;
  State *states[MAX_STATES];
} StateMachine;
Answer from nmichaels on Stack Overflow
Top answer
1 of 5
13

It looks like you're not allocating space for your states in the machine past the first one.

StateMachine * create_state_machine(const char* name) {
  StateMachine * temp;

  temp = malloc(sizeof(struct StateMachine));

  if (temp == NULL) {
    exit(127);
  }

  temp->name = name;
  temp->total_states = 0;

  temp->states = malloc(sizeof(struct State)); // This bit here only allocates space for 1.
  return temp;
}

You're probably better off putting an array of states of fixed size in the state machine struct. If that's not okay, you'll have to realloc and move the whole set around or allocate chunks and keep track of the current length, or make a linked list.

Incidentally, init, foo, and bar never get used.

Edit: What I'm suggesting looks like this:

#define MAX_STATES 128 // Pick something sensible.
typedef struct StateMachine {
  const char * name;
  int total_states;
  State *states[MAX_STATES];
} StateMachine;
2 of 5
12

It looks like you want to have a variable number of states in each state machine, but you are allocating the memory incorrectly. In create_state_machine, this line:

temp->states = malloc(sizeof(struct State));

Allocates a single State object, not an array of pointers (which is how you are using it).

There are two ways you could change this.

  1. Declare states as State states[<some-fixed-size>]; but then you cant ever have more than a fixed number of states.
  2. Add another member to indicate how much storage has been allocated for states, so you can keep track of that as well as how much is used (which is what total_states is being used for).

The later would look something like this:

#include <stdlib.h>
#include <string.h>

typedef struct 
{
    const char *name;
} State;

typedef struct 
{
    const char *name;
    int total_states;
    int states_capacity;
    State *states;
} StateMachine;

StateMachine *create_state_machine(const char *name)
{
    StateMachine *temp = malloc(sizeof(StateMachine));
    memset(temp, 0, sizeof(*temp));

    temp->name = name;
    temp->states_capacity = 10;
    temp->states = malloc(sizeof(State) * temp->states_capacity);

    return temp;
}

State *add_state(StateMachine *machine, const char *name)
{
    if (machine->total_states == machine->states_capacity)
    {
        // could grow in any fashion.  here i double the size, could leave
        // half the memory wasted though.
        machine->states_capacity *= 2;

        machine->states = realloc(
            machine->states, 
            sizeof(State) * machine->states_capacity);
    }

    State *state = (machine->states + machine->total_states);
    state->name = name;

    machine->total_states++;

    return state;
}
🌐
Reddit
reddit.com › r/cprogramming › how to create an array with unknown size?
r/cprogramming on Reddit: How to Create an array with unknown size?
March 11, 2020 -

I have participated in many coding competitions but I'm unable to pass all the test cases just because of this problem. I don't know how to initialize an array with unknown size. I tried using

arr=malloc(size*sizeof(int));

But at the end it shows segmentation fault. Can someone explain why?

Discussions

Struct unknown size
Hello, I’m currently working on an inventory system, I need to make an Array out of my struct, this is the code of the struct: and this is the code of the array: I’m new to c++ so It’s probably not the cleanest code you’ve ever seen, the problem is, I get this error: And no matter what ... More on forums.unrealengine.com
🌐 forums.unrealengine.com
1
1
March 2, 2021
c - Pointer in Struct -- unknown sized array - Stack Overflow
I am trying to implement a TLV (Type-Length-Value) in C, however I am having issues with getting the dynamic size of value to work correctly. ... typedef struct __attribute__((packed)){ unsigned char type; unsigned char length; unsigned char * value; } TLV; I am trying to cast an array to the ... More on stackoverflow.com
🌐 stackoverflow.com
May 24, 2017
gcc - C Struct array member without specific length - Stack Overflow
It's a C99 feature, called flexible array member which is typically used to create a variable length array. It can only be specified as the last member of a struct without specifying the size (as in array_field [];). More on stackoverflow.com
🌐 stackoverflow.com
February 23, 2016
c++11 - C++ How to initialize array in struct of unknown size - Stack Overflow
So I have this structure definition in my header file, inside this structure is an array of another structure. I want to read in the size of this array from a file, but I just can't figure out how. More on stackoverflow.com
🌐 stackoverflow.com
March 13, 2015
🌐
Arduino Forum
forum.arduino.cc › projects › programming
Array problem : type containing an unknown-size array is not allowed - Programming - Arduino Forum
May 7, 2017 - I need to create a structure like sort of tree. But I'm stuck at a point. Here is the code. typedef struct { String Name; uint8_t Age; uint8_t Toys; } Child; typedef struct { String Name; uint8_t Age; Child Children[]; } Parent; Parent Parents[] = { { "Parent 1", 40, { {"Child 1", 2} , {"Child 2", 5} , {"Child 3", 10} , } }, { "Parent 2", 45, { {"Child 1", 4} } } }; void PrintAllInfo() { uint8_t parentsCount = sizeof(Parents);//may not return 2 fo...
🌐
Shivankaul
shivankaul.com › blog › zero-length-arrays
Zero-length arrays in C have to go at the end of the struct
July 3, 2017 - If instead of data[0] the original programmer had written data[] (as defined by C99), then when I moved the member to any place other than the last, I would have gotten the error field has incomplete type (the compiler thinks you’re trying to initialize a normal array). However, as the syntax variable_name[0] exercises a language extension (which at this point exists for backwards compatibility), the only way to get GCC to grumble was by passing in -pedantic to get a measly warning about how ISO C forbids zero-size arrays.
Top answer
1 of 2
5

value is not array, it's a pointer (which is pointing somewhere outside the struct). If you want array (of unknown size), write unsigned char value[1] instead.

typedef struct __attribute__((packed)) {
    unsigned char type;
    unsigned char length;
    unsigned char value[1];
} TLV;

Having an array of size 1 allows you to actually address any number of bytes. That is actually UB, but it is actually used and works properly in all cases I saw.

GCC allows to use arrays of size 0. I am so used to that convention that I forgot that arrays of size 0 are not allowed in C.

Edit:

Long answer

There is a difference between arrays and pointers. While you can use the similar code to work with both, these are still different beasts.

Disclaimer: The following code works in gcc, but it might not be strictly valid. I did not try to make it completely valid.

Let's define two structures:

typedef struct {
    char p[20];
} sa;

typedef struct {
    char *p;
} sp;

And create instances of those:

sa x = { "Hello, world" };
sp y = { "Howdy, world" };

What's the difference between those two?

printf("%s\n", x.p); // prints "Hello, world"
printf("%s\n", y.p); // prints "Howdy, world"

What about addresses of these?

printf("address of x = %p\n", &x); // On my machine it prints 0x7fffacce9b20
printf("address of y = %p\n", &y); // 0x7fffacce9b10

Well.. not really interesting except that these numbers are .. quite similar - both structures are located in about the same spot - in my case it's stack, end of address space, but could be somewhere else.

printf("address of x.p = %p\n", &x.p); // 0x7fffacce9b20
printf("address of y.p = %p\n", &y.p); // 0x7fffacce9b10

Same numbers. As expected actually.

printf("address of x.p[0] = %p\n", &x.p[0]); // 0x7fffacce9b20 - same as before
printf("address of y.p[0] = %p\n", &y.p[0]); // 0x400764 - could be anything

Now these are different. The string "Hello, world" is located in the same spot as structure x, while string "Howdy, world" is located somewhere else - data segment, somewhere in the beginning of address space, but, again could be somewhere else.

So this is the difference: array is some data stored "here", while pointer is only address of the data stored "somewhere".

In your case you want to be able to keep the data somewhere "here" - right after the type and length. This is why you need arrays, not pointers.

I can not find any proof that the TLV implementation above is not UB, but I saw a lot of cases where array of chars was "parsed" by casting it to pointer to some structure. I even wrote a code like this myself.

0-size arrays

As I said before, arrays of size 0 are not allowed by C standard. But they are allowed by GCC and this is handy because it allows you to do the following:

typedef struct {
    unsigned char type;
    unsigned char length;
    unsigned char value[0];
} TLV;

int required_length = 10;
TLV *tlv = (TLV *) malloc(sizeof(TLV) + required_length);

Without 0-size arrays you'd have to add (or subtract? subtract I guess) 1 somewhere in the code above.

2 of 2
-1

The following is almost entirely portable and certainly not UB due to aliasing because at no point is test dereferenced so you can forget about it.

What isn't (technically) portable is the assumption that there's no internal padding in the struct TLV.

To obtain portability I've removed the __attribute__((packed)).

If your compiler supports it then you are 100% in the clear with no UB.

That is unless you change value to an aligned type then you are likely to be broken. This all works because sizeof(unsigned char) has to be 1 and type alignment has to divide their size. Remember, if it doesn't malloc(n*sizeof(T)) for some type T is broken as an array of n elements of type T. The C standard is painted into a corner that unsigned char can't be aligned because it's always legit to treat memory as an array of char (either kind).

So the following program will either fail at the assert(.) or execute successfully. On all known platforms it will execute successfully as there are no known platforms that would choose to internally pad the given data structure - whether you specify packed or not.

But why do this:

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>


typedef struct {
   unsigned char type;
   unsigned char length;
   unsigned char value;
} TLV;

static TLV dummy;

int main(void) {

    //There's no standard way to verify this at compile time.
    //NB: If you stick with packing or leave all the members of TLV the same type
    //Then this is almost certainly NOT an issue.
    //However the cast of test implicitly assumes the following is the case.
    //Here's a run-time check of a static constraint.
    assert(offsetof(TLV,value)==(sizeof(dummy.type)+sizeof(dummy.length)));

    unsigned char test[5] = {(unsigned char)'T', 0x03, 0x01, 0x02, 0x03};

    TLV* tlv=(TLV*)test;

    for(unsigned char i=0;i<tlv->length;++i){
        printf("%u\n",(&tlv->value)[i]);
    }

    (&tlv->value)[0]=253;
    (&tlv->value)[1]=254;
    (&tlv->value)[2]=255;

    for(unsigned char i=0;i<tlv->length;++i){
        printf("%u\n",(&tlv->value)[i]);
    }

    return EXIT_SUCCESS;
}

When you can do this (C99 onwards I'm told) and have no crappy alignment problems:

#include <stdlib.h>
#include <stdio.h>

typedef struct {
   unsigned char type;
   unsigned char length;
   unsigned char value[];//Variable length member.
} TLV;

int main(void) {

    TLV* tlv=malloc(sizeof(TLV)+3*sizeof(unsigned char));

    tlv->type='T';
    tlv->length=3;
    tlv->value[0]=1;
    tlv->value[1]=2;
    tlv->value[2]=3;

    for(unsigned char i=0;i<tlv->length;++i){
        printf("%u\n",tlv->value[i]);
    }

    tlv->value[0]=253;
    tlv->value[1]=254;
    tlv->value[2]=255;

    for(unsigned char i=0;i<tlv->length;++i){
        printf("%u\n",tlv->value[i]);
    }

    free(tlv);

    return EXIT_SUCCESS;
}

Notice that there is no compliant guaranteed way of allocating such things statically because there is no compliant guaranteed way of dictating the layout (and in particular size) of the structure so you cannot know how much space to allocate in the char array.

You can (of course) blend the solutions but if you pack the structure you are likely to break alignment of value (if something needing alignment) and if you don't risk the compiler internally padding TLV. That internal padding is unlikely in the current guise but actually very likely if you upgraded length to type of size_t - which is the natural 'full' answer.

The current length limit of 255 (on almost all platforms) is frankly stingy. It felt mean in 1993 writing in Turbo Pascal. In 2015 it's piffling. At least implement length as `unsigned int' unless you know such a tight ceiling is sufficient.

🌐
Cuni
d3s.mff.cuni.cz › legacy › ~holub › c_features.html
Lesser known C features
// initializing an array of int int a[ 7] = { [5]=1, [2]=3, 2}; // resulting in int a[ 7] = { 0, 0, 3, 2, 0, 1, 0}; // initializing an array of struct struct { int x,y; } ar[ 4] = { [1].x=23, [3].y=34, [1].y=-1, [1].x=12}; // resulting in struct { int x,y; } ar[ 4] = { { 0, 0}, { 12, -1}, { 0, 0}, { 0, 34}}; // interesting usage char forbidden[ 256] = { ['a']=1, ['e']=1, ['i']=1, ['o']=1, ['u']=1};
Find elsewhere
🌐
Stack Overflow
stackoverflow.com › questions › 29025797 › c-how-to-initialize-array-in-struct-of-unknown-size
c++11 - C++ How to initialize array in struct of unknown size - Stack Overflow
March 13, 2015 - You cannot do that. Your alternatives are to set a maximum size or to use vector<Struct2>. ... Alrighty thanks, I'll just use vector. ... In order to close the question, I will write the answer.
🌐
Quora
quora.com › How-do-I-declare-an-array-of-undefined-or-no-initial-size
How to declare an array of undefined or no initial size - Quora
Answer (1 of 7): well to define an array it's compulsory for it to cover some space in the memory. But it's possible for it to be NULL initially or have no list. eg: 1. ` int arr[];` -> will be wrong because we are not giving any size to it; 2. ` int *arr=NULL; //fun(arr); arr= new int[5];` -...
Top answer
1 of 2
2

Yes, it's called flexible array member. It's usually used with dynamically allocated objects. However, you cannot return Minefield by value. The compiler will copy only sizeof(Minefield) data what is the size of object if length of array Minefield::field was 0.

You can do:

Minefield* NewGame(int columns, int rows, int mines)
{
    Cell cells[columns*rows];
    ...
    // allocate memory for Minefield and cells array just after it
    Minefield* minefield = malloc(sizeof(*minefield) + sizeof cells);
    if (!minefield) { ... error handling ... }

    // set normal fields using compund literal
    *minefield = (Minefield){columns, rows, mines};

    // copy cells `array` to `minefield->field` array
    memcpy(minefield->field, cells, sizeof cells);

    return minefield;
}

The memcpy can be avoided by first allocating Minefield and writing directly to field member.

Minefield* NewGame(int columns, int rows, int mines)
{
    Minefield* minefield = malloc(sizeof(Minefield) + rows * columns * sizeof(Cell));
    if (!minefield) { ... error handling ... }
    *minefield = (Minefield){columns, rows, mines};

    Cell *cells = minefield->field;
    ...
    return minefield;
}
2 of 2
0

Unfortunately, C doesn't have any built-in dynamic array like python. However, if you want to use some dynamic array either you can implement your self or you can see the answer to that link C dynamically growing array which explains that you need to have starting array with a default size, and then you can increase the size of the array which depends on your algorithm. After you import that header file provided by @casablance, you can simply use it for your minesweeper game.

🌐
Stack Overflow
stackoverflow.com › questions › 72083069 › how-to-store-an-array-of-values-of-unknown-size-in-a-struct
c - How to store an array of values of unknown size in a struct - Stack Overflow
Community Asks Sprint Announcement - October/November 2025 · We’re releasing our proactive anti-spam measure network-wide · Opinion-based questions alpha experiment on Stack Overflow · 1 malloc() of struct array with varying size structs · 0 Dynamic Array of Structures · 4 dynamic array with unknown size ·
🌐
GeeksforGeeks
geeksforgeeks.org › c language › flexible-array-members-structure-c
Flexible Array Members in a structure in C - GeeksforGeeks
August 20, 2024 - The structure must contain at least one more named member in addition to the flexible array member. ... In the above code snippet, the size i.e. length of array "stud_name" isn't fixed and is a FAM.
🌐
Stack Overflow
stackoverflow.com › questions › 33934310 › how-to-allocate-memory-for-unknown-size-struct-array-in-c
how to allocate memory for unknown size struct array in C - Stack Overflow
November 26, 2015 - List structure allow you allocate one element every time you add new element. Or you can double resizing mechanism to resize your array. you must use two variables: one to store the current size, one to store the max size of array. When the current size larger than the max size, you use "realloc" function to re allocate your array with the new size by the double of current max size
🌐
Medium
medium.com › @zgza778 › c-arrays-why-unknown-sizes-are-allowed-4265aebbf50b
C Arrays: Why Unknown Sizes Are Allowed | by Phoebe Theresa Peters | Medium
April 4, 2025 - However, you can create a new array of a larger size and copy the elements from the old array to the new one. There are also dynamic alternatives like List which provides more flexibility when the size isn’t known in advance. C Arrays: Why Unknown Sizes Are Allowed This article explores a nuanced exception to the fixed-size rule. C arrays are widely used in various programming scenarios. They are particularly useful when dealing with collections of data where the size is known in advance.
🌐
Stack Exchange
cs50.stackexchange.com › questions › 43439 › how-to-set-loop-limit-on-an-array-with-unknown-size
cs50x - How to set loop limit on an array with unknown size - CS50 Stack Exchange
December 1, 2022 - Malan's phonebook1.c which enables the user to determine the size of the phonebook, as well as the contents. So far, it works exactly as I hoped. (if you see any errors or design flaws, let me know!) #include <stdio.h> #include <cs50.h> #include <string.h> typedef struct { string name; string number; } person; int main(void) { int size = get_int("How many contacts are in this phonebook?\n"); person people[size]; for (int i = 0; i < size; i++) { string who = get_string("Name of contact:\n"); string phone = get_string("Phone number:\n"); people[i].name = who; people[i].number = phone; } for (int j = 0; j < size; j++) { printf("%s: %s\n", people[j].name, people[j].number); } for (int k = 0; k < size; k++) { if (strcmp(people[k].name, "David") == 0) { printf("Number found: %s\n", people[k].number); return 0; } } printf("Not found/n"); return 1; }
Top answer
1 of 2
1

My question now is: (1) How can I iterate through this files struct pointer (Pseudocode: for each file in files) when (2) the amount of file_ts in it is unknown at compile time and also (3) the size of each file_t is unknown at compile time?

Let's start from statement (3): the good news, for you, is that the size of each file_t is absolutely known at compile time. It will be the size of a char * added to the size of an integer, and you can obtain that whenever you need it with sizeof(file_t).

Not the bad new: Since statement (2) is true (the amount of file_ts in it is unknown at compile time) unfortunately the answer to (1) is: you can't. At least, you can't without modifying something.

In order to know how many items there are in your struct files_t list (that is having a way to iterate through it) you have to options:

  1. Add a field to struct files_t containing the number of items:
    struct files_t {
        file_t *file;
       unsigned int nrOfFiles;
    };

You will take care to initialize it to 0, to increment it whenever you add a file to the list and to decrement it whenever you remove a file from it. You can iterate through it with a for loop with something like for(int i=0; i<filesList.nrOfFiles; i++).

  1. Design a sentinel value. A sentinel value is something meaning "this is the last element of the array". For example:
struct files_t {
    file_t *file;
};

struct file_t {
    unsigned char *bytes;
    unsigned int len;
};

struct file_t fileArray =
{
  { charPointer0, len01 },
  { charPointer1, len1 },
  /* ... */
  { charPointerN, lenN },
  /* Sentinel */
  { NULL, 0 }
};

struct files_t fileList = { fileArray };

In this case you can iterate until the { NULL, 0 } element is found.

2 of 2
1

The problem is not at compile time but at execution time, almost all is always unknown at compile time.

Your alone problem concerns the unknown numbers of elements in your arrays, if you have no way to have these numbers you can mark the end of each :

  • the last file_t can have its field bytes valuing NULL. I use the pointer rather than len to allow you to manage empty files
  • the last pointer in the array of files_t can be NULL
Top answer
1 of 2
7

The latter is called a "flexible array member" which is a special case for structures. The last member of a struct is allowed to have no specified size.

As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.

Also see example 20.

The former is a normal array and it's not allowed to have zero size. See 6.7.6.2 Array declarators.

If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. In other words, the language standard says so.

2 of 2
3

In your first example, you have defined a regular array without giving its size.

This is not legal in C. Outside of a struct, your array needs a size when you declare it, as you have no way to set the size later:

int main()
{
  unsigned char data[100];

  return 0;
}

In your second example, you have defined a flexible array member.

This is a legal operation in C that allows you to allocate memory for the array when you allocate memory for the struct. The flexible array member must be the last element in your struct.

Here is an example, based on the one from GCC's documentation:

struct line
{
  int length;
  char contents[]; // Flexible array member
};

struct line *myline = malloc(sizeof(struct line) + 100); // 100 bytes for the array
myline->length = 100;
🌐
Wikipedia
en.wikipedia.org › wiki › Flexible_array_member
Flexible array member - Wikipedia
February 7, 2026 - C struct data types may end with a flexible array member with no specified size: typedef struct { size_t len; // there must be at least one other data member double arr[]; // the flexible array member must be last // The compiler may reserve extra padding space here, like it can between struct ...
Top answer
1 of 2
14

You should store a pointer in your struct:

Vertex *vertices;

Then allocate the memory at runtime:

myFile f;
f.vertices = malloc(nVertices * sizeof(Vertex));
if (f.vertices == 0)
    handle_out_of_memory();

f.nVertices = nVertices;

Remember to free the memory when done:

free(f.vertices);
2 of 2
10

C99 introduces 'flexible array members', which may be what you want to use. Your code still ends up looking remarkably like the code suggested by @frast, but is subtly different.

§6.7.2.1 Structure and union specifiers

A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.

[...]

As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. With two exceptions, the flexible array member is ignored. First, the size of the structure shall be equal to the offset of the last element of an otherwise identical structure that replaces the flexible array member with an array of unspecified length.106) Second, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.

EXAMPLE Assuming that all array members are aligned the same, after the declarations:

struct s { int n; double d[]; };
struct ss { int n; double d[1]; };

the three expressions:

sizeof (struct s)
offsetof(struct s, d)
offsetof(struct ss, d)

have the same value. The structure struct s has a flexible array member d.

If sizeof (double) is 8, then after the following code is executed:

struct s *s1;
struct s *s2;
s1 = malloc(sizeof (struct s) + 64);
s2 = malloc(sizeof (struct s) + 46);

and assuming that the calls to malloc succeed, the objects pointed to by s1 and s2 behave as if the identifiers had been declared as:

struct { int n; double d[8]; } *s1;
struct { int n; double d[5]; } *s2;

Following the further successful assignments:

s1 = malloc(sizeof (struct s) + 10);
s2 = malloc(sizeof (struct s) + 6);

they then behave as if the declarations were:

struct { int n; double d[1]; } *s1, *s2;

and:

double *dp;
dp = &(s1->d[0]); // valid
*dp = 42; // valid
dp = &(s2->d[0]); // valid
*dp = 42; // undefined behavior

The assignment:

*s1 = *s2;

only copies the member n and not any of the array elements. Similarly:

struct s t1 = { 0 }; // valid
struct s t2 = { 2 }; // valid
struct ss tt = { 1, { 4.2 }}; // valid
struct s t3 = { 1, { 4.2 }}; // invalid: there is nothing for the 4.2 to initialize
t1.n = 4; // valid
t1.d[0] = 4.2; // undefined behavior

106) The length is unspecified to allow for the fact that implementations may give array members different alignments according to their lengths.

The example is from the C99 standard.