I would like to know if there is an elegant alternative to this:
struct A{
uint64_t w;
uint64_t x;
uint64_t y;
uint64_t z;
};
struct B{
uint32_t a;
uint16_t b;
};
void function(uint32_t length){
//we have one struct A at the head and multiple struct B.
struct B *ptr = malloc (length * sizeof B + sizeof A);
//we set random values in the head:
struct A * tmp = (struct A*)ptr;
tmp->w = 1000;
tmp->x = 1200;
tmp->y = 99;
tmp->z = ~(0ULL);
/*then we set the first element of type B.
*this is where my question lies
*/
// put the pointer at the right position:
tmp++;
//convert that position again:
struct B * right_position = (struct B*)tmp;
...// do things with B type.
}
Obviously, it would be simpler to have those fitted like so:
struct root{
struct A child1;
struct B *child2;
}
But my question is much more about the way to mark those offset down properly without writing the tmp++.
How could I directly access the first B element on that array without using tmp++?
Again, this is not how I would do it in real code. This is just.. kind of art we are discussing here, if you will :)
Perhaps struct B * right_position = (struct B*)((char *)ptr + sizeof(A));. The (char *) cast will make the calculation be performed in bytes.
struct A *a_ptr = malloc(sizeof(struct A) + length * sizeof(struct B));
struct B *b_ptr = (struct B *)(a_ptr + 1);
Maybe you should create a structure type with a flexible array member:
struct Both
{
struct A a;
struct B b[];
};
struct Both *c = malloc(sizeof(*c) + length * sizeof(c->b[0]));
c->a.w = 1000;
c->a.x = 1200;
c->a.y = 99;
c->a.z = ~(0ULL);
c->b[0].a = 37;
c->b[0].b = 59;
This guarantees alignment and doesn't require any casting or other chicanery. It's a part of C99 and C11 and replaces the struct hack. The standard (ISO/IEC 9899:2011) says:
§6.7.2.1 Structure and union specifiers
¶18 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.
The standard then has paragraphs 20-25 with examples discussing aspects of the use of flexible array members.
Related
I know that in C, the first member of a struct is guaranteed to have no padding before it. Thus &mystruct == &mystruct.firstmember is always true.
This allows the "struct inheritance" technique, as described in this question:
typedef struct
{
// base members
} Base;
typedef struct
{
Base base;
// derived members
} Derived;
// ... later
Base* object = (Base*) malloc(sizeof()); // This is legal
However, I'd like to make sure that this actually works safely with unlimited layers of "inheritance". E.g.:
typedef struct
{
// members
} A;
typedef struct
{
A base;
// members
} B;
typedef struct
{
B base;
// members
} C;
Are all of the following uses guaranteed to work?
A* a = (A*) malloc(sizeof(B));
A* a = (A*) malloc(sizeof(C));
B* b = (B*) malloc(sizeof(C));
C* c = malloc(sizeof(C));
// ... use and access members through the pointers
EDIT:
Let me clarify what I'm asking. Is the following use of "multi-level inheritance" guaranteed to work by the C standard?
C* c = malloc(sizeof(C));
// ... initialize fields in c
A* a = (A*) c;
// ... use A fields in a
B* b = (B*) a;
// ... use B fields in b
B* b = (B*) c;
// ... use B fields in b
c = (C*) a;
// ... go back to using C fields in c
That the kind of "multi-level inheritance" you describe must work follows from the same principles -- explained in the other Q&A you referenced -- that makes this kind of inheritance work at all. Specifically, the standard explicitly provides that casting the addresses of structures and of their initial members between the applicable types has the desired effect:
A pointer to a structure object, suitably
converted, points to its initial member [...] and vice versa.
(paragraph 6.7.2.1/15)
So consider this declaration, relative to the structure definitions provided:
C c;
The quoted provision specifies that &c == (C *) &c.base and (B *) &c == &c.base are both true.
But c.base is a B, so the provision also specifies that (A *) &c.base == &c.base.base and &c.base == (B *) &c.base.base are both true.
Since (B *) &c == &c.base is true and &c.base == (B *) &c.base.base are both true, it follows that (B *) &c == (B *) &c.base.base is also true.
Casting both sides to either A * or C * then produces also the equalities (A *) &c == &c.base.base and &c == (C *) &c.base.base.
This reasoning can be extended to an arbitrary nesting depth.
One can quibble a bit about dynamically allocated structures vis a vis the strict aliasing rule, but there's no reason to think that it is supposed to work any differently in that case, and as long as one first accesses the dynamically-allocated space via an lvalue of the most specific type (C in this example), I see no scenario that supports a different interpretation of the standard for the dynamic-allocation case than applies to other cases. In practice, I do not expect initial access via the most specific type actually to be required by any implementation.
What the ISO C standard requires to work is the following situation:
union U {
struct X x;
struct Y y;
struct Z z;
/* ... */
};
If the structures share some common initial sequence of members, then that initial sequence can be accessed through any of the members. For instance:
struct X {
/* common members, same as in Y and Z: */
int type;
unsigned flags;
/* different members */
};
If all the structures have type and flags in the same order and of the same types, then this is required to work:
union U u;
u.x.type = 42; /* store through x.type */
foo(u.y.type); /* access through y.type */
Other hacks of this type are not "blessed" by ISO C.
The situation you have there is a little different. It's question of whether, given a leading member of a structure, can we convert a pointer to the structure to that member's type and then use it. The simplest case is something like this:
struct S {
int m;
};
Given an object struct S s, we can take the address of m using &s.m, obtaining an int * pointer. Equivalently, we can obtain the same pointer using (int *) &s.
ISO C does require that a structure has the same address as its first member; a pointer to the structure and a pointer to the first member have a different type, but point to the same address, and we can convert between them.
This isn't restricted by nesting levels. Given an a of this type:
struct A {
struct B {
struct C {
int m;
} c;
} b
};
the address &a.b.c.m is still the same as the address &a. The pointer &a.b.c.m is the same as (int *) &a.
I have a C syntax question which is driving me crazy. I've defined some container structs:
typedef struct AStruct {
int importantData1;
int importantData2;
} A;
typedef struct BStruct {
A* arr1; // dynamic array of A structs
} B;
typedef struct CStruct {
B* arr2; // dynamic array of B structs
} C;
As you can guess, each A struct hold a part of my program's data. Each B struct holds an array of A's and each C struct holds an array of B's. I anticipate the need for only one C struct. So total amount of data with my C struct will be:
total data in C == (num of B's) * (num of A's)
The tricky part is I don't know how many A's and B's I'll need at compile time. This means I can't hardwire the array sizes; they must be dynamically allocated.
There's gotta be a way to do this. Here's my clunky attempt:
void makeContainers(C* x, int numB, int numA){
x->arr2 = (B*)malloc(numB * sizeof(B)); // allocate an array of empty B structs
B* Bptr;
int i;
for(i=0; i<numB; i++){
Bptr = x->arr2[i]; // Bptr is one of the B's in C's arr2
Bptr = (A*)malloc(numA * sizeof(A)); // Allocate an array of empty A stucts
}
}
int main() {
C* bigContainer = (C*)malloc(sizeof(C)); // Allocate the C struct
makeContainers(bigContainer, 8, 8); // populate C with B's and A's
return 0;
}
This looked great on paper... but the compiler hates the Bptr = x->arr2[i]; line. (Compiling with GCC on Linux) Here's the error:
[Linux]$ gcc -Wall setsInSets.c
setsInSets.c: In function ‘makeContainers’:
setsInSets.c:23:8: error: incompatible types when assigning to type ‘struct B *’ from type ‘B’
Bptr = x->arr2[i]; // Bptr is one of the B's in C's arr2
^
The "to type struct B from type B" part confuses me. Not sure what the compiler is trying to tell me here.
Also... This is kinda a C 101-type question, but I'm not certain I completely understand what the first line in makeContainers() is doing:
x->arr2 = (B*)malloc(numB * sizeof(B));
Here I am allocating memory for an array of B structs... but does that mean when this command is finished, I literally have an array of "empty" B structs ready to go? Or have I just set aside the memory, but the memory itself contains just "garbage"? In other words, do I have to walk the x->arr2 array and malloc() an individual B struct?
I know this is probably a duplicate question - but I ask it anyway because I think the "struct within a dynamic array within a struct within a dynamic array" nature of this question is pretty specific.
Thanks!
-Pete
x->arr2 is pointer to an array of B structs
x->arr2[i] is dereferencing one element in the array i.e. a B struct
To set a pointer you need the address of the struct
B* Bptr = &(x->arry[i]);
or more conveniently
B* Bptr = x->arry + i;
I would suggest you write the size of the array in your struct as well, it may come in handy later.
e.g.
typedef struct BStruct {
size_t elements; // to know how many A structs
A* arr1;
} B;
EDIT:
This part of the code
Bptr = x->arr2 + i; // Bptr is one of the B's in C's arr2
Bptr = malloc(numA * sizeof(A));
makes no sense, you first assign Bptr, then assigning it to another address.
I've recently found this page:
Making PyObject_HEAD conform to standard C
and I'm curious about this paragraph:
Standard C has one specific exception to its aliasing rules precisely designed to support the case of Python: a value of a struct type may also be accessed through a pointer to the first field. E.g. if a struct starts with an int , the struct * may also be cast to an int * , allowing to write int values into the first field.
So I wrote this code to check with my compilers:
struct with_int {
int a;
char b;
};
int main(void)
{
struct with_int *i = malloc(sizeof(struct with_int));
i->a = 5;
((int *)&i)->a = 8;
}
but I'm getting error: request for member 'a' in something not a struct or union.
Did I get the above paragraph right? If no, what am I doing wrong?
Also, if someone knows where C standard is referring to this rule, please point it out here. Thanks.
Your interpretation1 is correct, but the code isn't.
The pointer i already points to the object, and thus to the first element, so you only need to cast it to the correct type:
int* n = ( int* )i;
then you simply dereference it:
*n = 345;
Or in one step:
*( int* )i = 345;
1 (Quoted from: ISO:IEC 9899:201X 6.7.2.1 Structure and union specifiers 15)
Within a structure object, the non-bit-field members and the units in which bit-fields
reside have addresses that increase in the order in which they are declared. A pointer to a
structure object, suitably converted, points to its initial member (or if that member is a
bit-field, then to the unit in which it resides), and vice versa. There may be unnamed
padding within a structure object, but not at its beginning.
You have a few issues, but this works for me:
#include <malloc.h>
#include <stdio.h>
struct with_int {
int a;
char b;
};
int main(void)
{
struct with_int *i = (struct with_int *)malloc(sizeof(struct with_int));
i->a = 5;
*(int *)i = 8;
printf("%d\n", i->a);
}
Output is:
8
Like other answers have pointed out, I think you meant:
// Interpret (struct with_int *) as (int *), then
// dereference it to assign the value 8.
*((int *) i) = 8;
and not:
((int *) &i)->a = 8;
However, none of the answers explain specifically why that error makes sense.
Let me explain what ((int *) &i)->a means:
i is a variable that holds an address to a (struct with_int). &i is the address on main() function's stack space. This means &i is an address, that contains an address to a (struct with_int). In other words, &i is a pointer to a pointer to (struct with_int). Then the cast (int *) of this would tell the compiler to interpret this stack address as an int pointer, that is, address of an int. Finally, with that ->a, you are asking the compiler to fetch the struct member a from this int pointer and then assign the value 8 to it. It doesn't make sense to fetch a struct member from an int pointer. Hence, you get error: request for member 'a' in something not a struct or union.
Hope this helps.
I have to use the following block of code for a school assignment, STRICTLY WITHOUT ANY MODIFICATIONS.
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
pStudentRecord* g_ppRecords;
int g_numRecords =0;
Here g_ppRecords is supposed to be an array of pointers to structs. What I am completely failing to understand is that how can the statement pStudentRecords *g_ppRecords; mean g_ppRecords to be an array because an array should be defined as
type arrayname[size];
I tried allocating memory to g_ppRecords dynamically, but that's not helping.
g_ppRecords = (pStudentRecord*) malloc(sizeof(pStudentRecord*)*(g_numRecords+1));
EDIT: updated the "BIG MISTAKE" section.
A quick lesson on C-style (different from C++!) typedefs, and why it is how it is, and how to use it.
Firstly, a basic typedef trick.
typedef int* int_pointer;
int_pointer ip1;
int *ip2;
int a; // Just a variable
ip1 = &a; // Sets the pointer to a
ip2 = &a; // Sets the pointer to a
*ip1 = 4; // Sets a to 4
*ip2 = 4; // Sets a to 4
ip1 and ip2 are the same type: a pointer-to-type-int, even though you didn't put a * in the declaration of ip1. That * was instead in the declaration.
Switching topics.
You speak of declaring arrays as
int array1[4];
To do this dynamically at runtime, you might do:
int *array2 = malloc(sizeof(int) * 4);
int a = 4;
array1[0] = a;
array2[0] = a; // The [] implicitly dereferences the pointer
Now, what if we want an array of pointers? It would look like this:
int *array1[4];
int a;
array1[0] = &a; // Sets array[0] to point to variable a
*array1[0] = 4; // Sets a to 4
Let's allocate that array dynamically.
int **array2 = malloc(sizeof(int *) * 4);
array2[0] = &a; // [] implicitly dereferences
*array2[0] = 4; // Sets a to 4
Notice the int **. That means pointer-to pointer-to-int. We can, if we choose, use a pointer typedef.
typedef int* array_of_ints;
array_of_ints *array3 = malloc(sizeof(array_of_ints) * 4);
array3[0] = &a; // [] implicitly dereferences
*array3[0] = 4; // Sets a to 4
See how there's only one * in that last declaration? That's because ONE of them is "in the typedef." With that last declaration, you now have an array of size 4 that consists of 4 pointers to ints (int *).
It's important to point out OPERATOR PRECEDENCE here. The dereference operator[] takes preference over the * one. SO to be absolutely clear, what we're doing is this:
*(array3[0]) = 4;
Now, let's change topics to structs and typedefs.
struct foo { int a; }; // Declares a struct named foo
typedef struct { int a; } bar; // Typedefs an "ANONYMOUS STRUCTURE" referred to by 'bar'
Why would you ever typedef an anonymous struct? Well, for readability!
struct foo a; // Declares a variable a of type struct foo
bar b; // Notice how you don't have to put 'struct' first
Declaring a function...
funca(struct foo* arg1, bar *arg2);
See how we didn't have to put 'struct' in front of arg2?
Now, we see that the code you have to use defines a structure IN THIS MANNER:
typedef struct { } * foo_pointers;
That is analogous to how we did an array of pointers before:
typedef int* array_of_ints;
Compare side-by-side
typedef struct { } * foo_pointers;
typedef int* array_of_ints;
The only difference is that one is to a struct {} and the other is to int.
With our foo_pointers, we can declare an array of pointers to foo as such:
foo_pointers fooptrs[4];
Now we have an array that stores 4 pointers to an anonymous structure that we can't access.
TOPIC SWITCH!
UNFORTUNATELY FOR YOU, your teacher made a mistake. If one looks at the sizeof() of the type foo_pointers above, one will find it returns the size of a pointer to that structure, NOT the size of the structure. This is 4 bytes for 32-bit platform or 8 bytes for 64-bit platform. This is because we typedef'd a POINTER TO A STRUCT, not a struct itself. sizeof(pStudentRecord) will return 4.
So you can't allocate space for the structures themselves in an obvious fashion! However, compilers allow for this stupidity. pStudentRecord is not a name/type you can use to validly allocate memory, it is a pointer to an anonymous "conceptual" structure, but we can feed the size of that to the compiler.
pStudnetRecord g_ppRecords[2];
pStudentRecord *record = malloc(sizeof(*g_ppRecords[1]));
A better practice is to do this:
typedef struct { ... } StudentRecord; // Struct
typedef StudentRecord* pStudentRecord; // Pointer-to struct
We'd now have the ability to make struct StudentRecord's, as well as pointers to them with pStudentRecord's, in a clear manner.
Although the method you're forced to use is very bad practice, it's not exactly a problem at the moment. Let's go back to our simplified example using ints.
What if I want to be make a typedef to complicate my life but explain the concept going on here? Let's go back to the old int code.
typedef int* array_of_ints;
int *array1[4];
int **array2 = malloc(sizeof(int *) * 4); // Equivalent-ish to the line above
array_of_ints *array3 = malloc(sizeof(array_of_ints) * 4);
int a, b, c, d;
*array1[0] = &a; *array1[1] = &b; *array1[2] = &c; *array1[3] = &d;
*array2[0] = &a; *array2[1] = &b; *array2[2] = &c; *array2[3] = &d;
*array3[0] = &a; *array3[1] = &b; *array3[2] = &c; *array3[3] = &d;
As you can see, we can use this with our pStudentRecord:
pStudentRecord array1[4];
pStudentRecord *array2 = malloc(sizeof(pStudentRecord) * 4);
Put everything together, and it follows logically that:
array1[0]->firstName = "Christopher";
*array2[0]->firstName = "Christopher";
Are equivalent. (Note: do not do exactly as I did above; assigning a char* pointer at runtime to a string is only OK if you know you have enough space allocated already).
This only really brings up one last bit. What do we do with all this memory we malloc'd? How do we free it?
free(array1);
free(array2);
And there is a the end of a late-night lesson on pointers, typedefs of anonymous structs, and other stuff.
Observe that pStudentRecord is typedef'd as a pointer to a structure. Pointers in C simply point to the start of a memory block, whether that block contains 1 element (a normal "scalar" pointer) or 10 elements (an "array" pointer). So, for example, the following
char c = 'x';
char *pc = &c;
makes pc point to a piece of memory that starts with the character 'x', while the following
char *s = "abcd";
makes s point to a piece of memory that starts with "abcd" (and followed by a null byte). The types are the same, but they might be used for different purposes.
Therefore, once allocated, I could access the elements of g_ppRecords by doing e.g. g_ppRecords[1]->firstName.
Now, to allocate this array: you want to use g_ppRecords = malloc(sizeof(pStudentRecord)*(g_numRecords+1)); (though note that sizeof(pStudentRecord*) and sizeof(pStudentRecord) are equal since both are pointer types). This makes an uninitialized array of structure pointers. For each structure pointer in the array, you'd need to give it a value by allocating a new structure. The crux of the problem is how you might allocate a single structure, i.e.
g_ppRecords[1] = malloc(/* what goes here? */);
Luckily, you can actually dereference pointers in sizeof:
g_ppRecords[1] = malloc(sizeof(*g_ppRecords[1]));
Note that sizeof is a compiler construct. Even if g_ppRecords[1] is not a valid pointer, the type is still valid, and so the compiler will compute the correct size.
An array is often referred to with a pointer to its first element. If you malloc enough space for 10 student records and then store a pointer to the start of that space in g_ppRecords, g_ppRecords[9] will count 9 record-pointer-lengths forward and dereference what's there. If you've managed your space correctly, what's there will be the last record in your array, because you reserved enough room for 10.
In short, you've allocated the space, and you can treat it however you want if it's the right length, including as an array.
I'm not sure why you're allocating space for g_numRecords + 1 records. Unless g_numRecords is confusingly named, that's space for one more in your array than you need.
Here g_ppRecords is supposed to be an array of pointers to structs. What I am completely failing to understand is that how can the statement *pStudentRecords g_ppRecords; mean g_ppRecords to be an array. as an array should be defined as
type arrayname[size];
umm type arrayname[size]; is one way of many ways to define an array in C.
this statically defines an array, with most of the values being stored on the stack depending the location of it definition, the size of the array must be known at compile time, though this may no longer be the case in some modern compilers.
another way would be to dynamically create an array at runtime, so we don't have to know the size at compile time, this is where pointers come in, they are variables who store the address of dynamically allocated chunks of memory.
a simple example would be something like this type *array = malloc(sizeof(type) * number_of_items); malloc returns a memory address which is stored in array, note we don't typecast the return type for safety reasons.
Going back to the problem at hand.
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
pStudentRecord* g_ppRecords;
int g_numRecords = 0;
this typedef is a bit different from most note the }* basically its a pointer to a struct so this:
pStudentRecord* g_ppRecords;
is actually:
struct
{
char* firstName;
char* lastName;
int id;
float mark;
}** pStudentRecord;
its a pointer to a pointer, as to why they would define the typedef in this way, its beyond me, and I personally don't recommend it, why?
well one problem woud be how can we get the size of the struct through its name? simple we can't! if we use sizeof(pStudentRecord) we'll get 4 or 8 depending on the underlying architecture, because thats a pointer, without knowing the size of the structure we can't really dynamically allocated it using its typedef name, so what can we do, declare a second struct such as this:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
} StudentRecord;
g_ppRecords = malloc(sizeof(StudentRecord) * g_numRecords);
Either way you really need to contact the person who original created this code or the people maintaining and raise your concerns.
g_ppRecords=(pStudentRecord) malloc( (sizeof(char*) +
sizeof(char*) +
sizeof(int) +
sizeof(float)) *(g_numRecords+1));
this may seem like one possible way, unfortunately, there are no guarantees about structs, so they can actually containg padding in between the members so the total size of the struct can be actually larger then its combined members, not to mention there address would probably differ.
EDIT
Apparently we can get the size of the struct by simply inferring its type
so:
pStudentRecord g_ppRecords = malloc(sizeof(*g_ppRecords) * g_numRecords);
works fine!
I implement a file's struct in my program but for some arrays in the struct I don't know the size. The size of the array is stored in another variable but it's unknown before the struct is filled in.
struct Vertex {
float x;
float y;
float z;
};
struct myFile {
ulong nVertices;
Vertex vertices[nVertices];
};
That gives an error: "error C2065: 'nVertices' : undeclared identifier".
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);
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.