C Diverse Structures

Let's say I have the following structures:

struct StructA { int some_member; double some_other_member; }; struct StructB { char a_char; char another_char; }; 

Now say that I have a buffer in memory containing a bunch of these structures, and I would like to analyze it. Each structure in the buffer is preceded by an int describing the type of structure. Like this:

 struct Descriptor { int type; union { struct StructA a; struct StructB b; } data; }; 

What I would like to do is to point the pointer to the buffer ( char * ) to struct Descriptor * , read the type, then access the correct member of the union, and then move the pointer to the size of the member type + size of the correct member of the union (e.g. sizeof(int) + sizeof(struct StructA) ).

However, will it be a valid C code? (In the sense that this does not cause undefined behavior.) My main problem is that the memory buffer may be smaller than sizeof(struct Descriptor) , since it contains only StructB and a field of the previous type.

Is it legal to use a pointer to a structure when the underlying memory is insufficient to store the entire structure, although I only have access to the real part of the memory? Edit: if this is not valid for a structure, is it legal for a union?

If not, is there a better way? I found this comment and the answer to which it is made, but it deals with an array of the full size of the structure.

+5
source share
2 answers

I think it is valid as long as you search for the pointer correctly, i.e. do not touch data beyond the size of the buffer, which, I assume, you know in advance and correctly relate to alignment. Therefore, you just need to worry about the proper handling of the memory buffer, in addition to being the standard that should say about such a conversion

6.3.2.3 Pointers

  1. A pointer to an object type can be converted to a pointer to another object type. If the resulting pointer is not correctly aligned 68) for the reference type, the behavior is undefined. Otherwise, when converting back, the result is equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the low address byte of the object. Successive increments of the result, up to the size of the object, give pointers to the remaining bytes of the object.

68) In general, the concept of “correctly aligned” is transitive: if a pointer to type A is correctly aligned for a pointer to type B, which, in turn, is correctly aligned for a pointer to type C, then a pointer to type A is correctly aligned for a pointer to type C.

Then this is what he says about the appointment

6.5.16.1 Simple assignment

Semantics

  1. If the value stored in the object is read from another object that somehow overlaps the storage of the first object, then the overlap must be accurate, and the two objects must have qualified or unqualified versions of a compatible type; otherwise, the behavior is undefined.

So, if the overlap is accurate, you are just perfect and the behavior is defined.

+2
source

No, using a simple sizeof to calculate the offset is wrong, because it does not take into account a possible addition.

You should use the offsetof macro defined in stddef.h, which will work with any add-on:

 struct Descriptor* s = /*member data.a is initialized*/; const size_t aoff = offsetof( struct Descriptor , data.a ); const size_t doff = offsetof( struct StructA , some_other_member ); double* p = ( double* )( ( unsigned char* )s + aoff + doff ); 

p now points to the some_other_member member in the data.a of s member.

+4
source

Source: https://habr.com/ru/post/1240231/


All Articles