TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

The Lost Art of C Structure Packing

284 pointsby tadasvover 10 years ago

29 comments

herfover 10 years ago
In some cases you can benefit by &quot;struct of arrays&quot; instead of &quot;array of structs&quot;. This benefits packing, enables SIMD, and usually improves persistence speed too. Database people call this a &quot;column store&quot;. So if you abstract it a little you can do per-column compression that is really hard to do with vanilla structs.<p>One thing I learned with Picasa (which is basically an in-memory database): if you&#x27;re storing a lot of data in RAM, sometimes you should think of the data structures more as a database (with copy in&#x2F;out, rather than reference). In multithreaded cases, this kind of approach unexpectedly gets you more parallelism and speed.
评论 #9070215 未加载
评论 #9074618 未加载
评论 #9070486 未加载
评论 #9070249 未加载
评论 #9077059 未加载
评论 #9071474 未加载
评论 #9070241 未加载
评论 #9075154 未加载
ghshephardover 10 years ago
This was the cause of my very first &quot;hard&quot; C Bug, in 1991 or so. I had written a program in our Novell Netware labs to read in the printer control code definitions for our printer-release consoles - being &quot;clever&quot;, and wanting to save a few lines of code, I read them into a memory structure, and overlaid a C-Struct on top of them that mapped precisely to the fields that I wanted. Everything worked fine, code compiled, and we were able to read all the job definitions until I handed it off to the team responsible for the rest of the release console - at which point the code just started breaking. No longer worked. For the life of me I couldn&#x27;t figure out what was going, until our team leader took a glance, and made it clear that I needed to inform the compiler to byte align the C Structs (which was likely the default behavior in Turbo-C, but not Watcom C).<p>Really opened my eyes to the many, many things that I didn&#x27;t know.
geronimogarciaover 10 years ago
This was discussed like a year ago in HN <a href="https://news.ycombinator.com/item?id=6995568" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=6995568</a>
评论 #9069467 未加载
Dav3xorover 10 years ago
Decent article full of good information. One exception -- the C standard is vague on how bitfields are implemented and the compiler can rearrange them in any way it pleases. You are not guaranteed efficient packing, placement order, or size.
评论 #9070055 未加载
评论 #9071036 未加载
jgrahamcover 10 years ago
Sometimes this sort of stuff can really bite you: <a href="http://blog.jgc.org/2007/04/debugging-solaris-bus-error-caused-by.html" rel="nofollow">http:&#x2F;&#x2F;blog.jgc.org&#x2F;2007&#x2F;04&#x2F;debugging-solaris-bus-error-caus...</a>
drvover 10 years ago
The article goes into more detail on the &quot;why&quot;, but the &quot;art&quot; is not really that complicated or lost: sort structure elements by size&#x2F;alignment, biggest first.
评论 #9069540 未加载
评论 #9070057 未加载
评论 #9069589 未加载
评论 #9071727 未加载
lzybkrover 10 years ago
Most commonly used compilers have options to help find padding that is possibly not needed.<p>VC++ has a couple of undocumented (but well known and discussed) options &#x2F;d1reportAllClassLayout and &#x2F;d1reportSingleClassLayout.<p>GCC has -fdump-class-hierarchy<p>CLANG has -cc1 -fdump-record-layouts
评论 #9069744 未加载
pjaover 10 years ago
If anyone wants to take a look at the struct offsets inside their own code, the article mentions pahole as being a useful tool but I found that it chokes on recent C++ - the dwarf libraries it relies on can&#x27;t cope with lambdas and various other things IIRC.<p>However, helpful people have written an extension to gdb which does something roughly equivalent &amp; lets gdb do all the heavy lifting of parsing the struct data from the binary debugging information.<p>pahole.py ships with Fedora, but since Debian doesn’t include it for some reason I’ve kept my own versions around based on something I grabbed from the gdb mailing lists some time ago:<p><a href="https://github.com/PhilArmstrong/pahole-gdb" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;PhilArmstrong&#x2F;pahole-gdb</a>
评论 #9070986 未加载
Animatsover 10 years ago
In Pascal, you could just declare a structure as &quot;packed&quot;, and this packing happened automatically. &quot;packed array [0..n] of Boolean&quot; is an array of bits. That feature has not been copied in more recent languages.
评论 #9070031 未加载
评论 #9069873 未加载
elrosover 10 years ago
Interesting to discover that this is a &quot;lost art&quot;.<p>I didn&#x27;t graduate, but I did attend PUC-Rio for a while and I remember professor L. F. Bessa Seibel&#x27;s lecture about that, as part of the INF1008 class (Introduction to Computers&#x27; Architecture), which is considered a basic first or second semester course for undergraduate CS students.<p>That was just 5 years ago.<p>Great class, great lecturer, btw
t1mover 10 years ago
I am going to suggest that &#x27;Structure Packing&#x27; isn&#x27;t the lost art. I think the lost art is &#x27;Variable Sized Structs&#x27;, the emphasis on the last &#x27;s&#x27; of &#x27;Structs&#x27;.<p>This is the situation where your solution calls for an array of structs that are contiguous in memory but aren&#x27;t the same size. This happens oftenish in database, os, and compression tech. C99 and gcc have legalized the often used convention:<p><pre><code> struct varb { char *foo; unsigned char age; int number_of_bars; char var[]; &#x2F;&#x2F; it&#x27;s something like var[0] in GCC, or var[1] in versions &lt; c99 }; </code></pre> where the last element is actually the start of the variable length piece. In all the C supported implementations of var length structs, we have limitations:<p>- the variable part must be declared last<p>- the struct may not appear in other structs or arrays<p>which totally makes sense, but doesn&#x27;t help us implement a contiguous array of variable length structs. Also, the restriction of having the variable part of the struct come last may waste a lot of space if we have a structure where we would rather optimize the order of the struct ourselves, but that&#x27;s another post!<p>Assume we are OK with the limitations of our <i>struct varb</i>, we now need to declare and <i>malloc</i> (or <i>mmap</i>) a <i>char</i>* (to hold all of our data) and lay out our <i>varb structs</i> fairly manually. Once we have found the start of a particular <i>varb struct</i>, we can cast it&#x27;s <i>char</i>* address to a <i>struct varb</i>* and the compiler then can help us populate or interrogate our data. Note that we will need to keep track of detailed memory usage &#x27;so far&#x27; when we are populating as well track padding, alignment of adjacent <i>structs</i>, as well as any reallocation when our <i>struct</i> array needs to grow.
评论 #9072601 未加载
devbugover 10 years ago
Rust does structure packing automatically.<p>This is great for the general programmer (someone who is not knowledgeable or caring about details like this.)<p>Unfortunately, this blows for people who do (someone like me.)
评论 #9071731 未加载
评论 #9069776 未加载
评论 #9069656 未加载
评论 #9070949 未加载
评论 #9069722 未加载
wilaover 10 years ago
The article doesn&#x27;t appear to mention it, but in the past I had a need for this type of information when interfacing C data structures from other programming languages.<p>If the structure you are connecting with is packed you have to be aware of that or else you&#x27;ll end up with data soup :)
noelwelshover 10 years ago
One of the many reasons that Rust is interesting is you can play these games if you are interested in performance or size: <a href="http://doc.rust-lang.org/book/ffi.html#interoperability-with-foreign-code" rel="nofollow">http:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;ffi.html#interoperability-with...</a>
girvoover 10 years ago
Is it really a lost art? I&#x27;ve recently been learning C and C++, and all three of the textbooks I&#x27;ve been studying have mentioned in, and two go very in-depth on it (one of those is a games programming textbook). This is a great resource though, definitely going to add it to my studies.
unwindover 10 years ago
This was rather readable, more so than I&#x27;ve come to expect from that particular source.<p>Still, I must point out that using a signed 1-bit bitfield (there are <i>lots</i> of those in that article), is generally a bad idea. Consider for instance something like:<p><pre><code> struct foo6 { int bigfield:31; &#x2F;* 32-bit word 1 begins *&#x2F; int littlefield:1; }; </code></pre> That &quot;littlefield&quot; member is signed but has a size of just one bit, which means it is limited to representing the two values 0 and -1 (in two&#x27;s complement). This is very seldom useful. The general rule of thumb is to always make &quot;boolean&quot;-type bitfields have an unsigned type, for this reason.
source99over 10 years ago
I&#x27;m guessing it&#x27;s a lost art because available system memory is much larger and many programs are written in other languages these days.
评论 #9069711 未加载
TazeTSchnitzelover 10 years ago
A good portion of PHP 7&#x27;s performance improvements came from better structure packing:<p><a href="https://wiki.php.net/phpng-int" rel="nofollow">https:&#x2F;&#x2F;wiki.php.net&#x2F;phpng-int</a><p><a href="http://nikic.github.io/2014/12/22/PHPs-new-hashtable-implementation.html" rel="nofollow">http:&#x2F;&#x2F;nikic.github.io&#x2F;2014&#x2F;12&#x2F;22&#x2F;PHPs-new-hashtable-impleme...</a>
评论 #9070453 未加载
sprw121over 10 years ago
Or we could use __attribute__((packed))?
评论 #9070461 未加载
评论 #9069719 未加载
评论 #9069963 未加载
评论 #9070766 未加载
jherikoover 10 years ago
i definately agree with the &#x27;lost art&#x27; part. i&#x27;ve been stunned to find programmers who don&#x27;t understand this and make arguments like &quot;the compiler optimises that for you&quot;... so much so that i&#x27;ve written my own piece on this, and more than once (and in more or less detail in various places - i.e. bitfields):<p><a href="http://jheriko-rtw.blogspot.co.uk/2011/02/know-your-cc-struct-layout-rules.html" rel="nofollow">http:&#x2F;&#x2F;jheriko-rtw.blogspot.co.uk&#x2F;2011&#x2F;02&#x2F;know-your-cc-struc...</a><p><a href="http://jheriko-rtw.blogspot.co.uk/2012/01/c-struct-layout-optimisation-revisited.html" rel="nofollow">http:&#x2F;&#x2F;jheriko-rtw.blogspot.co.uk&#x2F;2012&#x2F;01&#x2F;c-struct-layout-op...</a>
CountHackulusover 10 years ago
How about the lost art of COBOL record packing where COBOL records are like a combination of C&#x27;s union and structs. It was great you could sometimes squeeze a few extra bits out in one case to use better in another case.
jobuover 10 years ago
Years ago I worked on a few projects that used complicated structure ordering, but even then it was my understanding that (with the right options) compilers could optimize these things better than most people could by hand.
评论 #9069857 未加载
shultaysover 10 years ago
Don&#x27;t elements of structures are sorted before even packing starts? For example char c; int i; char c2;<p>I thought in reality c2 starts after c. Instead of adding padding between each element, you will only need in boundaries
评论 #9069432 未加载
评论 #9071117 未加载
评论 #9069442 未加载
gambitingover 10 years ago
I&#x27;ve actually had a question about this on my programming interview for a games development company. And yes, I have had to use it several times since. So no, the art is definitely not lost :-)
pfortunyover 10 years ago
Very interesting and very detailed, and very informative and also, useful. So, a great read.
frozenportover 10 years ago
Standard warning message in PVS studio. Not sure why the compiler doesnt warn about it.
评论 #9069749 未加载
PSeitzover 10 years ago
This is no lost art, this is pretty well known for proficient c developers. There is even an Wikipedia article. <a href="http://en.wikipedia.org/wiki/Data_structure_alignment" rel="nofollow">http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Data_structure_alignment</a>
jongraehlover 10 years ago
I guess we&#x27;re probably ok with the Y2118 cvs-export bug.
user_robover 10 years ago
I have always found that typedef does an admiral job of packing the data.