Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the size the trailing padding of a struct or class?

Tags:

c++

c

struct

sizeof can be used to get the size of a struct or class. offsetof can be used to get the byte offset of a field within a struct or class.

Similarly, is there a way to get the size of the trailing padding of a struct or class? I'm looking for a way that doesn't depend on the layout of the struct, e.g. requiring the last field to have a certain name.

For the background, I'm writing out a struct to disk but I don't want to write out the trailing padding, so the number of bytes I need to write is the sizeof minus the size of the trailing padding.

CLARIFICATION: The motivation for not writing the trailing padding is to save output bytes. I'm not trying to save the internal padding as I'm not sure about the performance impact of non-aligned access and I want the writing code to be low-maintenance such that it doesn't need to change if the struct definition changes.

like image 219
Joshua Chia Avatar asked Oct 27 '25 06:10

Joshua Chia


2 Answers

The way a compiler can pad fields in a structure is not strictly defined in the standard, so it's a kind of free choice and implementation dependent. If a data aggregate have to be interchanged the only solution is to avoid any padding.
This is normally accomplished using a #pragma pack(1). This pragma instructs the compiler to pack all fields together on a 1 byte boundary. It will slow the access on some processors, but will make the structure compact and well defined on any system, and, of course, without any padding.

like image 130
Frankie_C Avatar answered Oct 28 '25 19:10

Frankie_C


pragma pack or equivalent is the canonical way to do that. Apart from that I can only think of a macro, if the number of members is fixed or the maximum number is low, like

$ cat struct-macro.c && echo
#include<stdio.h>

using namespace std;

#define ASSEMBLE_STRUCT3(Sname, at, a, bt, b, ct, c) struct Sname {at a; bt b; ct c; }; \
       int Sname##_trailingbytes() { return sizeof(struct Sname) - offsetof(Sname, c) - sizeof(ct); }

ASSEMBLE_STRUCT3(S, int, i1, int, i2, char, c)

int main()
{
        printf("%d\n", S_trailingbytes());
}
$ g++ -Wall -o struct-macro struct-macro.c && ./struct-macro
3
$

I wonder if something fancy can be done with a variadic template class with in C++. But I can't quite see how the class/structure can be defined and the offset function/constant be provided without a macro again -- which would defeat the purpose.

like image 39
Peter - Reinstate Monica Avatar answered Oct 28 '25 19:10

Peter - Reinstate Monica



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!