Sizeof () part of structure C - view

I want to capture some of the data inside some C structures to partially serialize / deserialize them, write bytes from memory to disk, and vice versa.

Structures are not known in advance, they are dynamically built with my own C code generator (as well as code that will serialize it). Serializable fields will be placed at the beginning of the structure.

Let's say a has a structure with 4 fields, and the first two must be serialized:

typedef struct { int8_t x1; int32_t x2; /* 1 + 4 = 5 bytes (if packed) */ int8_t y1; int32_t y2; /* 1 + 4 +1 + 4 = 10 bytes (if packed) */ } st; 

I plan to grab a pointer to a structural variable and write / read bytes n that span the first two fields ( x1, x2 ). I don’t think that I need to worry about alignment / packaging, because I do not intend to serialize in order to survive in different compilations (it is expected that only a unique executable will read / write data). And, since I am targeting a wide range of architecture compilers, I don't want to post assumptions about alignment or compilation settings.

Then I need to count bytes. And I can't just do sizeof(st.x1)+sizeof(st.x2) because of add-on. So, I plan to subtract the pointers, starting from the beginning of the structure to the first "unsaturated" field:

 st myst; int partsize = (char*)&myst.y1 - (char*)(&myst); printf("partial size=%d (total size=%d)\n",partsize,sizeof(myst)); 

It seems to work. And it can be placed in a macro.

(For the record: I tried to write another macro that does not require repeating an instance of the structure, something like this , but here it is not possible - but this is not very important to me).

My question is: is this correct and safe? Can you see a potential trap or some better approach?

Among other things: do C allow standard (and de facto compilers) that the structs fields are in memory in the same order in which they are defined in the source? This is probably a stupid question, but I want to be sure ...

UPDATE: some conclusions from the answers and my own conclusions:

  • There seems to be no problem with my approach. In particular, C indicates that the structure fields will never change order.

  • You can also (as was suggested by aswer) calculate from the last constant field and add its size: (char*)&myst.x2 + sizeof(&myst.x2) - (char*)(&myst) . This would be equivalent, except that it would include non-padding bytes (if any) for the last field. A very small advantage - and a very small disadvantage - is to be less simple.

  • But the accepted answer with offsetof seems to be preferable to my suggestion. This is a clear, expressive and pure compilation time; it does not require an instance of the structure. It also seems standard, available in any compiler. Unless you need a compile-time construct and have an instance of an accessible structure (like my script), both solutions are equivalent.

+8
c struct
source share
5 answers

Have you looked at the offsetof object? It returns the offset of the member from the beginning of the structure. Therefore, offsetof (st, x2) returns the offset x2 from the beginning of the structure. So in your example, offsetof (st, x2) + sizeof(st.x2) will give you the number of bytes of serialized components.

This is very similar to what you are doing now, you can just ignore the indentation after x2 and use the rarely used piece of C.

+10
source share

C guarantees this behavior. It is designed to provide primitive polymorphism. Consider:

 struct X { int a; }; struct Y { int a; int b; }; void foo(X* x) { x->a = 10; }; Y y; foo((X*)&y); // Well defined behaviour- ya = 10. 
+5
source share

C complier can insert padding bytes for alignment, but cannot reorder structure variables.

A simpler way would be to simply define a 2nd structure for sizeof () purposes, which includes the initial variables of the desired structure. The compiler guarantees that 2 racks that have the same variables in the same order will be the same.

+3
source share

You can take a look at protobuf ; he seems to be doing what you want, figuratively.

0
source share

I vote for the KISS principle. Write a file element by element, and you do not guarantee any compiler dependencies.

0
source share

All Articles