Search code examples
cstructcompiler-construction

Compute address of struct field given struct address


Given a packed (i.e. assume that there is no alignment) struct:

struct Foo {
  int x;
  int y;
};

struct Foo *foo;

Is it "safe" (i.e. it is defined somewhere in the standard) to translate &foo->y as foo + sizeof(int) (i.e. the address of foo->y is equal to the address of foo added with size of int) ?

I'm following the C11 standard 6.2.6 Representations of types but it says nothing about how fields are stored in a struct.


Solution

  • As the compiler author, you get to choose the amount and size of any padding.

    The standard says that you must allocate the members "sequentially" (section 6.2.5, paragraph 20, p. 42) and that, except for bit-fields, they occupy bytes (6.2.6.1, pp. 44-45). Not much else is required in most cases.

    (Edit: one other requirement is that the first member have offset zero. See section 6.7.2.1, paragraph 15, p. 113.)

    ABIs may make their own more-stringent requirements. In general, as a compiler writer, you probably should not insert "unnecessary" padding, but it's up to you to define "unnecessary" here. If you support some form of "packed" keyword or attribute, use it to enable or disable padding inserted for clear performance gains (e.g., padding that aligns a 4-byte int on a 4-byte boundary). If moving an int to a cache line boundary might improve performance, but might not, leave that to the user.