1

I have two ways to arrange the fields in a structure

 struct foo { float a; double b; float c; double d; short e; long f; short g; long h; char i; int j; char k; int l; }; struct foo { double b; double d; long f; long h; float a; float c; int j; int l; short e; short g; char i; char k; }; 

Which one should be practiced and why?

6
  • 2
    This sounds eerily like homework. I'll throw in one word: Padding. You can figure out the rest, I guess. Commented Nov 16, 2013 at 13:21
  • A4L, it's not strictly a style/opinion question as the order can actually impact the total memory needed for the struct and execution speed, thanks to padding. Depends a lot on the compiler and flags used though, and the impact is not likely to be significant in most circumstances. Commented Nov 16, 2013 at 13:34
  • 1
    @A4L Thank you, will remember in the future! Commented Nov 16, 2013 at 13:48
  • Just do printf("%d\n", sizeof(struct foo)) for each variant, and you'll know which one is better and precisely why... Commented Nov 16, 2013 at 13:59
  • @a4l, I'm pretty sure in your language of choice (which seems to be Java) the same issues apply. It's just that in most languages (Java included), your view of the program is so high level and your care for performance so minimal that you never hear discussions about such things. Nevertheless, the impact of padding on cache and alignment impact on memory access from the point of view of the processor are completely unrelated to the programming language. Commented Nov 16, 2013 at 15:21

4 Answers 4

2

The best way to arrange members of a structure is to put them in increasing order, by their size. Doing this, you reduce the padding, required for data alignment.

Also, using some preprocessor directives you modify the alignment, for example:

#define packed_data __attribute__((__packed__)) 

turns it off. Using this, the member order doesen't matter anymore, but I strongly discourage this, as the memory alingnment is optimised for performance.

Sign up to request clarification or add additional context in comments.

4 Comments

It does not matter if you sort for increasing or decreasing size, as long as you sort by size. Sorting for increasing size will distribute the padding to the different section ends, sorting for decreasing size will make a solid data block with all the padding applied at the end. The amount of padding is the same, only the distribution is not.
@JonasWielicki I see, you're correct. The sorting was what escaped me, and I will gladly drop the comment. Thank you very much for pointing that out. Much appreciated.
@cmaster Jonas just pointed out that very thing, and I apologize for not seeing that (still 6:30am here and coffee is sparse-at best). I'll gladly drop the inaccurate comment. Thank you to both of you for the sanity check. And +1 on the comment, btw.
I was going to present a counter example, but ended up with this!
1

The Second arrangement is preferable.

In structs, to minimise the loss of bit storage due to padding

(the boundary alignment of various variables in the memory) , it is preferable to start

the structure with variables of the largest size. Go from higher to lower size.

  1. See Padding in structures

  2. Size of variable types in C

    (http://www.cquestions.com/2011/02/size-of-data-types-in-c.html)

Comments

0

One sensible way of ordering fields is by their similarity of purpose. For instance:

struct window { MENU *menu ; int width ; char *name ; WINDOW *child ; int xpos ; int height ; void *info ; WINDOW *next ; CLASS *class ; int ypos ; WINDOW *parent ; } 

would look better as

struct window { CLASS *class ; void *info ; char *name ; int xpos ; int ypos ; int width ; int height ; WINDOW *parent ; WINDOW *next ; WINDOW *child ; MENU *menu ; } 

Comments

0

Padding is one reason to favor one arrangement over another. Another option is to sort the fields by their frequency or by their memory access pattern. This is of course micro-optimization, but it can pay off in extreme cases.

Many, or most CPU architectures encode smaller offsets in pointers with smaller opcodes; Putting the most frequently accessed element to offset zero can in especially RISC architectures reduce the number of instructions, as well as make the code run faster.

If 'x' is used at the same time as 'y', it's beneficial to put them in the same cache line instead of face the risk of two or more cache misses per structure.

2 Comments

At least with the RISC architectures I know of, they actually care less for things like offset sizes or offsets being zero than CISC architectures. The reason is that RISC architectures have a fixed command size (usually 32 bits), into which quite a bit of information can be packed. Not using these bits would simply be a waste of precious space. On the Power platform, for instance, there are commands with five(!) arguments in the range 0 to 32. Likewise, you don't have any simplified versions of commands like loads and stores. All memory accesses allow an offset, that's the simplicity.
If RISC means fixed instruction length, then by definition. Cortus APS3 e.g. has 16/32-bit instructions, but because os load/store architecture and fixed instruction throughput, is very much a RISC. Omitting also the question, in which category ARM actually belongs, it has similar properties.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.