There’s no “step-by-step” here. When initialization is performed with constant expressions, the process is essentially performed at compile time. Of course, if the array is declared as a local object, it is allocated locally and initialized at run-time, but that can be still thought of as a single-step process that cannot be meaningfully subdivided.
Designated initializers allow you to supply an initializer for a specific member of struct object (or a specific element of an array). All other members get zero-initialized. So, if my_data
is declared as
typedef struct my_data { int a; const char *name; double x; } my_data;
then your
my_data data[]={ { .name = "Peter" }, { .name = "James" }, { .name = "John" }, { .name = "Mike" } };
is simply a more compact form of
my_data data[4]={ { 0, "Peter", 0 }, { 0, "James", 0 }, { 0, "John", 0 }, { 0, "Mike", 0 } };
I hope you know what the latter does.