17

I use g++ to compile code with packed fields. However, I receive an error when trying to return a reference to a packed field.

Example:

struct __attribute__((packed)) Foo {
   int* ptr;
   uint16_t foo;
   int*& getPtr(){
      return ptr;
   }
};

yields error:

test.cpp:22:14: error: cannot bind packed field ‘((Foo*)this)->Foo::ptr’ to ‘int*&’
   return ptr;

Why can't I return a reference to a packed field?

David G
  • 94,763
  • 41
  • 167
  • 253
gexicide
  • 38,535
  • 21
  • 92
  • 152

1 Answers1

4

There is a gcc bug report Cannot bind packed field that covers this and it says:

The C++ spec (C++03, Sects. 3.9, 3.9.1, 3.9.2) are very clear that T and "pointer to T" have implementation-specific alignment requirements. If you have a "pointer to T" then you may assume that it meets the alignment requirements. I'm sure the C spec has similar language.

In the OP's case, the following code could violate the alignment requirements

They suggest a workaround using alignment attribute to define your own aligned type but it does not look like it works.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Don't believe this, just found the same bug report and was about to post the exact same quote... – Columbo Dec 15 '14 at 19:22
  • I tried the workaround with the alginment attribute. It is simply ignored by my gcc. – gexicide Dec 15 '14 at 19:32
  • @gexicide The "workaround" looks like a hack that avoids the error message but doesn't actually work. Have `getPtr` return a proxy instead. – Marc Glisse Dec 15 '14 at 19:45
  • @MarcGlisse: What do you mean with proxy here? – gexicide Dec 15 '14 at 19:47
  • @gexicide an object that internally stores `Foo*` and allows manipulation of the `ptr` field. –  Dec 15 '14 at 19:49
  • http://en.wikibooks.org/wiki/More_C++_Idioms/Temporary_Proxy (or whatever else google comes up with), see `vector::operator[]` for an example. – Marc Glisse Dec 15 '14 at 19:50
  • 1
    If I can have a pointer to packet field, why can't I have a reference to packed field? The member's address is known in both cases. – Nuclear Mar 30 '15 at 06:39
  • 1
    Because not all platforms support byte addressable memory, and returning an unaligned structure will cause a run time segfault when the returned value is accessed. – Dan Apr 23 '18 at 21:12
  • @DanQ Can you elaborate? How is accessing the address the pointer points to any different than using the reference? – jterm Sep 06 '18 at 22:37
  • 1
    On architectures that aren't byte addressable,the compiler still lets you access non-aligned fields by doing memory transforms behind the scenes (e.g. masking and shifting) to get your desired value. It only knows to do this because the struct is packed at compile time. If the compiler loses that packed information, then it may try to directly access a memory location that's not supported and will hard fault. Even though in the OPs question it would make no difference, GCC plays it safe and disallows the operation. – Dan Sep 07 '18 at 02:30