copying a struct with a struct member to another struct - c

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.

Related

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
;

struct similarity in 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.

array of forward declared struct in another struct

I am trying to forward declare a struct A and define a struct B that contains an array of A.
I am getting error stating 'incomplete type not allowed'
This is what I have:
struct A;
struct B
{
// something
struct A x[10]; // This where I get the error incomplete type not allowed
};
struct A
{
// something
};
What am I doing wrong ?
As a work around you can declare a pointer to struct A as this
struct B
{
// something
struct A * x;
};
This is because if you have a line like
struct B b;
the b will have a member x[10]. If you did not fully declare struct A, struct B doesn't know how to allocate 10 struct A elements. In the workaround, if you only declare a pointer, struct B doesn't need to know how to allocate struct A but only need to know how to allocate one pointer.
An "incomplete type" (MSDN) is a type whose details the compiler doesn't know at a given point in the translation unit. In the declaration of members of struct B, the compiler doesn't know the size of the type (sizeof (struct A)) and therefore doesn't know how much space to leave for it. Another reason for not allowing struct members of incomplete type is that if they could, this would have allowed "circular composition" where struct A contains members of type struct B and vice versa. I don't see how the size of the result of such a circular composition could even be defined.
Workarounds:
To include struct A by value in struct B, complete the type first. Move the declaration of members of struct A above that of struct B.
A struct is allowed to include pointers to incomplete types as members. In struct B, include an array of pointers (struct A *x[10];) Then populate it with objects of type struct A allocated separately, possibly through some factory that calls malloc(sizeof(struct A)), fills out its members, and returns the pointer. You're then responsible for freeing the memory used by these instances.

Location of the struct when only the location of a member is given

Let us assume there is a struct with multiple members. The struct members are initialized with some values. The memory location of a specific member is given. Assume that you don't know the other members, their types, the ordering of members etc. Is there a way to know the memory location of the struct itself?
Is this problem called a specific name?
If you know the name of the struct, simply use offsetof
struct my_struct {
const char *name;
struct list_node list;
};
int main() {
struct my_struct t;
struct list_node* pl = &t.list;
size_t offset = offsetof(struct my_struct, list); //here
struct my_struct* pt = (struct my_struct*)((unsigned char*)pl-offset); //and here
}
If offsetof is not viable for what you're doing, then no, there's no other way. Offsetof can alternatively be written in standard C, but there's absolutely no good reason to do that.
If you know the structure type, then all you need is an offset of the field within the structure, subtract it from the member address and typecast result to pointer to the structure. For a practical implementation see FreeBSD's implementation of __containerof().
Hi Everyone I found the answer this
Cast a null pointer to the struct. You can get the offset by casting the resulting address(Offset) to a char*
(char *)(&((struct *)0)->member))
You could do any type*. But char* guarantees it's always the word size.
This should be how offsetof() is written as well

Why does "struct T* next" compile when T isn't an existing type?

I am using MinGW on Windows. I am building linked list and I am confused with this.
#include <stdio.h>
#include <stdlib.h>
typedef struct Data
{
int x;
int y;
struct BlaBla * next; /*compiles with no problem*/
}List;
int main(void)
{
List item;
List * head;
head = NULL;
return 0;
}
I now that struct can't have struct variable(object, instance of that struct), but can have pointer of that struct type. Didn't know that pointer can be pointer of unexisting type. struct BlaBla * next;(not for linked list, it must be struct Data * next but mean general talking)
Yes, you can, because then the compiler, upon encountering the unknown type name for the first time, assumes that there's somehwere a struct type definition with this name. Then it will forward-declare the struct name for you, let you use it as a pointer, but you can't dereference it nor can you do pointer arithmetic on it (since it's an incomplete type).
The compiler will accept code such as your example:
typedef struct Data
{
int x;
int y;
struct BlaBla * next; /*compiles with no problem*/
}List;
This is okay because the size of pointers is known to the compiler, and the compiler is assuming that the struct will be defined before it is dereferenced.
Because the compiler acts this way, it's possible to do this:
typedef struct Data
{
int x;
int y;
struct Data * next; /* points to itself */
} List;
However, if you were to include the struct inline, like this:
typedef struct Data
{
int x;
int y;
struct BlaBla blaStruct; /* Not a pointer. Won't compile. */
}List;
The compiler can't work out how big struct Data is because it doesn't know how big struct BlaBla is. To get this to compile, you need to include the definition of struct BlaBla.
Note that, as soon as you need to access the members of struct BlaBla, you will need to include the header file that defines it.
It depends on what you mean by "unexisting". If you haven't even declared BlaBla, you'll get an error.
If you've declared it but not yet defined it, that will work fine. You're allowed to have pointers to incomplete types.
In fact, that's the normal way of doing opaque pointers in C.
So, you might think that this is invalid because there's no declaration of struct BlaBla in scope:
typedef struct Data {
struct BlaBla *next; // What the ??
} List;
However, it's actually okay since it's both declaring struct BlaBla and defining next at the same time.
Of course, since definition implies declaration, this is also okay:
struct BlaBla { int xyzzy; };
typedef struct Data {
struct BlaBla *next; // What the ??
} List;
In order to declare a variable or field of a given type, pass one as a parameter, or copy one to another of the same type, the compiler has to know how many bytes the variable or field occupies, what alignment requirements it has (if any), and what other pointer types it's compatible with, but that's all the compiler needs to know about it. In all common dialects of C, a pointer to any structure will always be the same size and require the same alignment, regardless of the size of the structure to which it points or what that structure may contain, and pointers to any structure type are only compatible with other pointers to the same structure type.
Consequently, code which doesn't need to do anything with pointers to a structure except allocate space to hold the pointers themselves [as opposed to the structures at which they point], pass them as parameters, or copy them to other pointers, doesn't need to know anything about the structure type to which they point beyond its unique name. Code which needs to allocate space for a structure (as opposed to a pointer to one) or access any of its members must know more about its type, but code which doesn't do those things doesn't need such information.

Resources