Why would someone do this? Better yet how does this even work? I would have assumed this would somehow create an array of three structures with only the first member defined. I realize a pointer points to the first element of the array, and I see how this could work but how this is defined is throwing me off! (gcc 4.8.4)
void do_something(const void *);
typedef struct{
int a;
char b;
int c;
} the_data_t;
int main(int argc, char *argv[])
{
the_data_t my_data[] = {10, 'a', 30};
do_something((const void *)my_data);
}
void do_something(const void *data)
{
printf("data a: %d\ndata b: %c\ndata c: %d\n", ((the_data_t*)data)->a,
((the_data_t*)data)->b, ((the_data_t*)data)->c);
}
Output
data a: 10
data b: a
data c: 30
Regardless, I changed it to this..
int main(int argc, char *argv[])
{
the_data_t my_data = {10, 'a', 30};
do_something(&my_data);
}
I would have assumed this would somehow create an array of three structures with only the first member defined
No, it's not that way. Basically it creates an array of one element, with all the members intialized.
Quoting C11
, chapter §6.7.9
Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union. [...]
and
Each designator list begins its description with the current object associated with the closest surrounding brace pair. Each item in the designator list (in order) specifies a particular member of its current object and changes the current object for the next designator (if any) to be that member.150) The current object that results at the end of the designator list is the subobject to be initialized by the following initializer.
and
[...] If the initializer of a subaggregate or contained union begins with a left brace, the initializers enclosed by that brace and its matching right brace initialize the elements or members of the subaggregate or the contained union. Otherwise, only enough initializers from the list are taken to account for the elements or members of the subaggregate or the first member of the contained union; [...]
Basically, your code should ideally look like
the_data_t my_data[] = {{10, 'a', 30}};
to visualize initializing one element.
OTOH, what you expected may be achieved by
the_data_t my_data[] = {{10}, {'a'}, {30}};
where it creates an array of 3 elements, all having the member variable a
initialized.
That said,
the_data_t my_data[] = {{10, 'a', 30}};
is equivalent to writing
the_data_t my_data = {10, 'a', 30};
except the part, my_data
will not be an array anymore (but what good is an one element array, in general, either?).
Compiler will treat
the_data_t my_data[] = {10, 'a', 30};
as
the_data_t my_data[1] = {{ 10, 'a', 30 }}; // Though it will raise warning.
So, my_data
is an array of one the_data_t
type.
This is similar to when a two dimensional array is declared like this
int a[][3] = { 1, 2, 3 };
then compiler will treat it as
int a[1][3] = { { 1, 2, 3 } };
Print the size of a
and you will get 12
(if size of int
is 4
on that machine).
It's not proper. GCC will give you a warning for this:
warning: missing braces around initializer
warning: (near initialization for ‘my_data[0]’)
What it will do is create a 1 element array.
gcc will give you warning about this issue, if you use the warning switch.
$ gcc -Wall test.c
test.c: In function ‘main’:
test.c:14:25: warning: missing braces around initializer [-Wmissing-braces]
the_data_t my_data[] = {10, 'a', 30};
^
test.c:14:25: note: (near initialization for ‘my_data’)
$
To fix this either you can properly initialize the array as:
the_data_t my_data[] = {{10, 'a', 30}};
Or, as you showed in the post, you can change my_data
to a struct variable.
the_data_t my_data = {10, 'a', 30}; // And call do_something as
do_something((const void *)&my_data);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With