
The Lost Art of C Structure Packing - uyoakaoma
http://www.catb.org/esr/structure-packing/
======
justinplouffe
Awareness of the layout and size of data is still very common in game
development. Mike Acton did a great talk related to this at CppCon a few years
ago :
[https://www.youtube.com/watch?v=rX0ItVEVjHc](https://www.youtube.com/watch?v=rX0ItVEVjHc)

~~~
jzelinskie
This is true for high performance server software, too, especially servers
that resemble databases.

I personally find myself thinking about alignment more than I probably should.
For Go, I use [http://golang-sizeof.tips](http://golang-sizeof.tips) for
experimenting. I've been able to make schema changes to my structs to enable
more functionality without increasing memory usage.

------
valarauca1
Lost but not forgotten.

IDK, most these rules are very trivial and fairly simple to automate. Pretty
much boils down to declare the smallest fields first, with a handful of
exceptions based on the modulus of size.

Ultimately I like Rust’s approach. Without including
‘[repr(C)]/[repr(packed)]’ the compiler is free to layout the structure in the
most efficient way for the target platform. And accessing fields with
different compiler’s code is UB. You get the speed up, while keeping backwards
compatibility.

Sadly C/C++ are shackled to this archaic system. Also I believe Go, Nim, and
Swift are as well (this is speculation).

~~~
loeg
It's not even lost. Any C code that cares about performance will eventually
look into how structures are laid out in cache lines.

~~~
valarauca1
It is a requirement for code heavily using atomics as false shares and destroy
performance.

------
smeenai
clang-tidy has a struct padding check which diagnoses non-optimal struct
orders, and a coworker contributed a clang tool to reorder fields:
[https://github.com/llvm-mirror/clang-tools-
extra/tree/master...](https://github.com/llvm-mirror/clang-tools-
extra/tree/master/clang-reorder-fields)

~~~
nly
This makes sense if you're only concerned with size. Locality or eliminating
false sharing may be more important in large ones

------
shortlived
Not lost if you are programming on a mainframe... just not blogged about.

~~~
boznz
.. And not applicable to 8-bit embedded programmers.

~~~
Sinergy2
Are you sure? You can still declare a short field on a 8b micro.

~~~
FRex
What are the alignment requirements for one there though? Unaligned access can
come with performance cost or be impossible on 16 and 32 bit machines for some
cases (I don't know all the details for ARM and x86) but I'd assume (I don't
definitely KNOW, just making an educated guess) that an 8 bit machine that can
only do 8 bit operations doesn't need alignment at all and using a short (or a
long) always involves reading 8 bits twice (or 4 times) and any 8 bits at all
can be read so it can be packed completely tightly. Meanwhile (I'm again just
guessing, I'm not low level enough to know that), 16 and 32 bit machines try
to read it all in one go into a register and that's why they need alignment or
else they take the performance hit to read twice and mask out the value or
raise an exception.

This art is certainly not lost though it comes up with language VMs, native
compilers, Linux kernel, as a common curio about C and C++, etc.

------
kevin_clever
I tried the example below, saved as `main.c`. It seems she automatically
reorders the static mem. Can that behavior be disabled? Can someone please
explain?

    
    
        #include<stdio.h>
        int main(int argc, char** argv)
        {
        	char *p;
    	char c;
    	int x;
    
            printf("char p  %p\n", &p);
            printf("char    %p, offset %i\n", &c, (int)((void*)&c-(void*)&p));
            printf("integer %p, offset %i\n", &x, (int)((void*)&x-(void*)&p));
            return 0;
        }
    

Output on `gcc main.c; ./a.out`

    
    
        char p  0x7ffc5107dff0
        char    0x7ffc5107dfeb, offset -5
        integer 0x7ffc5107dfec, offset -4

~~~
kps
Those are not structure members. C provides no guarantees about the relative
locations of separate variables.

~~~
kevin_clever
So, it's a compiler specific reordering?

~~~
pjc50
Yes. Probably specific to compiler _options_ too. Only structure members have
a defined order.

------
drake01
I've found file: unaligned-memory-access.txt useful. Ref:- Linux Kernel
Source: UNALIGNED MEMORY ACCESSES Link:
[https://github.com/torvalds/linux/blob/master/Documentation/...](https://github.com/torvalds/linux/blob/master/Documentation/unaligned-
memory-access.txt)

------
ryanmccullagh
Hint, compile with -Wpacked

~~~
ramzyo
Have to disagree with you here, totally depends on the platform and if you
know what you’re doing. Compiling with this option can lead to unaligned
memory accesses. On some architectures, most ARM ones for example, unaligned
memory accesses lead to hard faults at runtime.

~~~
smitherfield
You're thinking of `#pragma pack`. `-Wpadded` just warns about non-optimal
layout.

~~~
ramzyo
Whoops, yes my bad. -Wpacked will just issue the warning, not actually do the
packing!

------
banned1
This is going to sound rude but it is not my intention. The reality is that
packing DOES NOT matter for most applications these days.

I read an article about a person who was the last in the world to speak some
obscure language. Some people wanted to start a school to teach others to
speak that language, wanted the government to pay for it, etc.

The two articles gave me the same combined feel of “I feel a little sorry but
not a lot” and “who cares.”

The compiler will take care of most.

Unfortunately for that person on the other article, he is basically screwed.

Don’t let that be you.

~~~
FRex
The compiler cannot reorder the fields. This stuff comes up occasionally in
optimizing layout of language VM structures, compilers, in the Linux kernel
and other low level situations.

I.e. JVM compressed object pointers rely on the alignment and the native
objects representation is definitely well laid out to not waste space due to
alignment:

[https://stackoverflow.com/a/25120926](https://stackoverflow.com/a/25120926)

[https://blog.codecentric.de/en/2014/02/35gb-heap-
less-32gb-j...](https://blog.codecentric.de/en/2014/02/35gb-heap-less-32gb-
java-jvm-memory-oddities/)

Lua implementation similarly cares about alignment in some cases:

[http://lua-users.org/lists/lua-l/2009-02/msg00305.html](http://lua-
users.org/lists/lua-l/2009-02/msg00305.html)

This is not exactly 'struct packing' but alignment is closely connected to
padding so its part of a wider interconnected topic.

