having hard time to understand the way memset() works. Does the Standard
(I'm interested in both C90 and C99) guarantee that the function will set to
0 all the bits of the structure's members ?
The memset function knows nothing about your structures and its
members, it simply sets all the bytes in a given "range" to a given
value. If the value is 0, and the "range" covers some object of a
struct type, then yes, all the bits of the structure's members will be
set to 0.
However, this doesn't mean the structure's members themselves will be
set to 0. The standard requires that all integral-typed objects having
all their bits set to 0 are themselves equal to 0, but the
representation of pointers and floating-point is unspecified, and
therefore - at least theoretically - having all their bits set to 0 is
not necessarily equivalent to having themselves equal to 0.
For example:
struct X
{
char a;
int b;
double c;
void* d;
} x;
memset(&x, 0, sizeof x);
printf("%d %d %f %d", x.a, x.b, x.c, x.d != NULL);
This will print two zeroes for x.a and x.b and two more values for x.c
and x.d which are most likely zeroes on mainstream platforms but not
necessarily. To be pedantic, the code above has undefined behaviour
because access to the values of x.c and x.d which at the point of
access are not properly initialized. However, on mainstream platforms
this will work perfectly OK.
Does the memset() act differently if a structure integrates unions ?
C has no reflection, so memset knows nothing about structures and
unions. All it knows about is memory which is made up by a sequence of
bytes.
struct X
{
char a;
union
{
int b;
double c;
void* d;
};
} x;
memset(&x, 0, sizeof x);
printf("%d %d %f %d", x.a, x.b, x.c, x.d != NULL);
This code will yield the same output as above (and all the
reservations are valid as well). Members x.b, x.c and x.d are
overlapping in the memory this time; but the bytes allocated to them
are still all zeroes.
Quoting ISO C99: "The memset function copies the value of c (converted to an
unsigned char) into each of the first n characters of the object pointed to
by s.", but as I understand this rule does not apply if the object is, say,
an array of 'ints' with sizeof(int) > 1. Perhaps I don't get it right at
all.
Why not? Arrays are placed in the memory contiguously, therefore you
can use memset to initialize arrays as well.
int i, x[100];
memset(&x, 0, sizeof x);
for (i = 0; i < 100; ++i) printf("%d ", x
);
This yields 100 zeroes. Assume, for example, that sizeof (int) == 4.
400 bytes are allocated for the array x. memset sets these 400 (sizeof
x) bytes to 0. Access to any x retrives corresponding 4 bytes out
of those 400, and those 4 bytes are all 0, making up the int value of
0.