2

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.

Ta Thanh Dinh
  • 638
  • 1
  • 5
  • 12
  • 2
    This is so close to [offsetof implementation](https://stackoverflow.com/questions/57342141/does-this-implementation-of-offsetof-invoke-undefined-behavior). Why not use offsetof? `(uintptr_t)(void*)foo + offsetof(struct Foo, y)` ? – KamilCuk Dec 04 '19 at 00:34
  • Thank you, but I cannot because I'm implementing a toy compiler for `C`. So I wonder if the data-layout of struct is defined somewhere. – Ta Thanh Dinh Dec 04 '19 at 00:39
  • 2
    Wouldn't it be up to your compiler to determine the (lack of) padding? I would think that would be standards compliant, but I can't quote anything. – LegendofPedro Dec 04 '19 at 00:54

1 Answers1

3

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.

torek
  • 448,244
  • 59
  • 642
  • 775
  • 3
    Also note that some architectures may fail to support direct unaligned memory accesses entirely; it's not necessarily just a matter of performance. Unless the asker carefully compiles memory accesses so that unaligned loads and stores perform correctly, padding may be necessary just for the code to run at all. – user3840170 Dec 04 '19 at 08:24