struct similarity in C - c

Consider the two structs below:
struct A {
double x[3];
double y[3];
int z[3];
struct A *a;
int b;
struct A *c;
unsigned d[10];
};
struct B {
double x[3];
double y[3];
int z[3];
};
Notice that struct B is a strict subset of struct A. Now, I want to copy the members .x, .y and .z from an instance of struct A to an instance of struct B. My question is: according to the standards, is it valid to do:
struct A s_a = ...;
struct B s_b;
memcpy(&s_b, &s_a, sizeof s_b);
I.e. is it guaranteed that the paddings for the members, in their sequence of appearance, will be the same, so that I can "partially" memcpy struct A to struct B?

It is not guaranteed that struct A's layout starts off the same as struct B's layout.
However, if and only if they were both members of a union:
union X
{
struct A a;
struct B b;
};
then it is guaranteed that the common initial sequence has the same layout.
I've never heard of any compiler that would lay out a struct differently if it detected that the struct were a member of a union, so in practice you should be safe!

How about using struct B as an anonymous struct member of struct A. This requires, however, -fms-extensions for gcc (there should be a similar extension for VC as the name implies):
struct B {
double x[3];
double y[3];
int z[3];
};
struct A {
struct B;
struct A *a;
int b;
struct A *c;
unsigned d[10];
};
This allows to use the fields in struct A like:
struct A as;
as.x[2] = as.y[0];
etc. This guarantees identical layout (the standard allows no padding at the beginning of a struct, so the inner struct is guarantee to start at the same address as the outer) and struct A being cast-compatible to struct B.
Also:
struct A as;
struct B bs;
memcpy(&as, &bs, sizeof(bs));

I do not think the Standard would prohibit an implementation from including so much more padding in s_a than s_b that the former is actually larger even though its members are a subset of s_b's. Such behavior would be very weird, and I can't think of any reason why a compiler would do such a thing, but I don't think it would be prohibited.
If the number of bytes copied is the lesser of sizeof s_a and sizeof s_b, then the memcpy operation will be guaranteed to copy all of the common fields, but would not necessarily leave the later fields of s_b undisturbed. On a typical machine, if the declarations had been:
struct A { uint32_t x; char y; };
struct B { uint32_t x; char y,p; uint16_t q; };
the first structure would contain five bytes of data and three bytes of padding, while the second would contain eight bytes of data with no padding. Using memcpy as shown in your code would copy the padding from s_a over the data in s_b.
If you need to copy the initial structure members while leaving the balance of the structure undisturbed, you should compute add offset and size of the last member of interest, and use that as the number of bytes to copy. In the example I give above, the offset of y would be 4, and the size would be 1, so the memcpy would thus ignore parts of the structure that are used as padding in A but might hold data in B.

Related

How to automatically pad bytes in a structure to a specific alignment?

For example, I have the following structure:
typedef struct st
{
char x1;
char x2;
...
char y;
}*st_p;
This definition of structure st may vary over time (it is not guaranteed what will be defined inside ... as development goes on).
Is there a way to guarantee that char y is always aligned on – for example – a 256-byte boundary?
I guess the solution is something like adding an array like the following:
typedef struct st
{
char x1;
char x2;
...
char padding[keyword];
char y;
}*st_p;
Is there such a keyword which calculates the total size of all previous members in this structure and which thereby helps resolve the number of bytes to pad?
Since C11, the C language includes the _Alignas attribute,1 with which you can specify a desired (minimum) alignment requirement for any object, including a member of a structure.
So, in your case, you can skip the 'manual' padding and just add that attribute to the char y; declaration:
typedef struct st {
char x1;
char x2;
//...
_Alignas(256) char y;
}*st_p;
1 However, note that the C Standard does not require that an implementation supports so-called "extended alignment" – that is, an alignment requirement that is greater than that of a max_align_t type (typically 8 or 16 bytes). What it does require, though, is that the specified alignment be a positive power of 2 (which is true, in your case).
As an addendum/alternative, I shall also address your direct question:
Is there such a keyword which calculates the total size of all previous members in this structure and which thereby helps resolve the
number of bytes to pad?
The 'keyword' (actually, an operator) that could be used here is sizeof – so long as you put "all previous members" inside an anonymous struct. Here's an example:
#include <stdio.h>
#include <stddef.h>
typedef struct st {
struct inner {
char x1;
char x2;
char x3[714];
//...
};
char padding[256 - sizeof(struct inner) % 256];
char y;
}*st_p;
int main()
{
struct st test;
test.x1 = 'A'; // You can access the anonymous structure members as though
test.x2 = 'B'; // they were 'direct' members of the enclosing structure.
printf("%c %c %zu\n", test.x1, test.x2, offsetof(struct st, y));// Offset is 768
return 0;
}
But note that, in this code, although the offset of y will be a multiple of 256 bytes, that doesn't guarantee that y will be 256-byte aligned. That will only be true in an instance of the st structure that is itself aligned on a 256-byte boundary … and to ensure that, you will need an alignment attribute on the structure itself.
It is possible to use the compiler attributes to tell it to align a particular structure field to a specific bound. For example, if you are using GCC, you can use:
__attribute__((aligned(n)))
Thus, your example would become:
typedef struct st
{
char x1;
char x2;
...
char __attribute__((aligned(256))) y;
}*st_p;
If you have to do this at several places, you can even imagine defining a special type for this, something like:
typedef char __attribute__((aligned(256))) aligned_char;
typedef struct st
{
char x1;
char x2;
...
aligned_char y;
}*st_p;
This is not limited to structures field, you can also apply this to local or global variables.
However, keep in mind this may not work with all compilers as the attributes are binded to the compiler and not the C language.
If you are using MSCV, you may be able to replicate the behavior with
__declspec(align(x))
Could use a union, but there is no .padding[] member. Could also use a check that the offset is correct in case the first struct is larger than desired offset.
#define OFFSET 256 /* Does not need to be a power-of-2 */
typedef struct st {
union {
struct {
char x1;
char x2;
};
struct {
char dummy[OFFSET];
};
};
char y;
} st;
void bar(void) {
st o1;
o1.x1 = '1';
o1.x2 = '2';
o1.y = 'y';
printf("%p\n", (void *) &o1);
printf("%p\n", (void *) &o1.y);
}
_Static_assert(offsetof(struct st, y) == OFFSET, "TBD code");
Sample output
0xffffcac0
0xffffcbc0
This does not insure the alignment is 256, but that the offset of member y is 256 - which I think is OP's true goal. #Adrian Mole

How does __attribute__((packed)) for a field affect struct which contains this field?

If I have a field in my struct which is packed, why my whole structure is becoming packed?
Example:
#include <stdio.h>
struct foo {
int a;
} __attribute__((packed));
struct bar {
char b;
struct foo bla;
char a;
};
int main() {
printf("%ld\n", sizeof(struct bar));
return 0;
}
https://ideone.com/bjoZHB
Sizeof of bar struct is 6, but it should be 12, because it should be aligned.
it seems because __attribute__((packed)) means use the minimum memory for structure, it also means that it can ignore alignment for siding members when it is in another structure. Check following structure:
struct bar {
char b;
__attribute__((packed)) int bla;
char a;
};
When you check size for this structure, it will be 6. This happens because it ignores member alignment for 2 side members(a and b here). But this structure:
struct bar {
char b;
__attribute__((packed)) int bla;
char a;
int c;
};
has size of 12, because it is aligned c on 4 bytes boundary. In your case, if you use aligned attribute too at same time, it works as you expect:
struct bar {
char b;
__attribute__((aligned (4), packed)) int bla;
char a;
};
This structure size is 12.
Update:
I only found this in GCC's aligned section of attributes. I think it is related to what I mentioned here:
The aligned attribute can only increase the alignment; but you can
decrease it by specifying packed as well
.Just remember that if you want to keep child structure packed but main structure aligned, you need to use 2 attributes in 2 different declarations. For example following structure has size of 12:
struct foo {
char b;
int a;
} __attribute__((packed));
struct bar {
char b;
__attribute__((aligned(4))) struct foo bla;
char a;
};
but if you use aligned() in declaration of foo as __attribute__((aligned (4), packed)), size will be 16. This happens because foo gets aligned too, and it will not be useful in case of packing.

Limitations in "struct inside struct"

There are 2 struct definitions A and A. I know that there is OK to struct A contain a POINTER to struct A but I don't understand why struct A cannot contains struct A (not a pointer)
Because when you put structs inside each other, you're putting another copy of that struct into the struct at that point. For example:
struct A {
int q;
int w;
};
struct B {
int x;
struct A y;
int z;
};
This will be laid out in memory like this:
int /*B.*/x;
int /*A.*/q;
int /*A.*/w;
int /*B.*/z;
But if you try to put a struct inside itself:
struct A {
int x;
struct A y;
};
you have an A, which contains an int and another A, which contains an int and another A, and now you have an infinite number of ints.
Because in that case, it will take infinite storage as it will have to recursively store the data member of its own type. So, it is not possible. Whereas, Size of a pointer is fixed and hence causes no problem.
Let's suppose it could contain an object of its own type:
struct A_
{
A_ a;
int b;
} A;
What's sizeof(A) ? Answer: sizeof(A)+sizeof(int): impossible.
Because the structure definition is not finished until the closing curly-brace }. To declare a structure member the compiler need the full definition, as it uses that information to calculate things like space and padding and alignment etc. For a pointer to something the size of the pointer is the size of the pointer, and all the compiler needs os the name of the type, not its full definition.
Lets take a simple structure for example:
struct A // Here the compiler knows that there is a structure named A
// The compiler does not know its contents, nor its size
{
// Some members...
struct A *pointer_to_a; // All the compiler needs to know is the symbol A
// The size and alignment is that of a pointer
// and those are known by the compiler
// Some more members...
// struct A instance_of_A; // This is not possible! At this point the
// compiler doesn't have the full definition
// of the structure, and can therefore not
// know how much space it need to allocate
// for the member
// Some even more members...
}
// Now the compiler knows the full contents of the structure, its size
// and alignment requirements
;

Using macro in C11 anonymous struct definition

The typical C99 way to extending stuct is something like
struct Base {
int x;
/* ... */
};
struct Derived {
struct Base base_part;
int y;
/* ... */
};
Then we may cast instance of struct Derived * to struct Base * and then access x.
I want to access base elements of struct Derived * obj; directly, for example obj->x and obj->y. C11 provide extended structs, but as explained here we can use this feature only with anonymous definitions. Then how about to write
#define BASE_BODY { \
int x; \
}
struct Base BASE_BODY;
struct Derived {
struct BASE_BODY;
int y;
};
Then I may access Base members same as it's part of Derived without any casts or intermediate members. I can cast Derived pointer to Base pointer if need do.
Is this acceptable? Are there any pitfalls?
There are pitfalls.
Consider:
#define BASE_BODY { \
double a; \
short b; \
}
struct Base BASE_BODY;
struct Derived {
struct BASE_BODY;
short c;
};
On some implementation it could be that sizeof(Base) == sizeof(Derived), but:
struct Base {
double a;
// Padding here
short b;
}
struct Derived {
double a;
short b;
short c;
};
There is no guarantee that at the beginning of the struct memory layout is the same. Therefore you cannot pass this kind of Derived * to function expecting Base *, and expect it to work.
And even if padding would not mess up the layout, there is a still potential problem with trap presenstation:
If again sizeof(Base) == sizeof(Derived), but c ends up to a area which is covered by the padding at the end of Base. Passing pointer of this struct to function which expects Base* and modifies it, might affect padding bits too (padding has unspecified value), thus possibly corrupting c and maybe even creating trap presentation.

copying a struct with a struct member to another struct

is the following code correct?
typedef struct
{
int x;
int y;
} OTHERSTRUCT;
struct DATATYPE
{
char a;
OTHERSTRUCT b;
}
// ...
// now we reserve two structs
struct DATATYPE structA;
struct DATATYPE structB;
// ... probably fill insome values
// now we copy structA to structB
structA = structB;
Are both structs now completely identical? Even the "struct in the struct"?
Thanks!
Yes.
When you assign one struct variable to another, every member is copied one-by-one, including the other struct OTHERSTRUCT you have as a member of DATATYPE.
Yes, their contents is the same afterwards.
There may well be padding bytes between a and b in struct DATATYPE, and these are not guaranteed to be copied by the struct assignment. That doesn't mean that they won't be, just that you can't rely on whether they are or not.
The actual members a and b will have identical values. The effect of the copy applies recursively to members of struct type, so yes the members-of-members are copied too.

Resources