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

1

18

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?

Gabriellia answered 15/12, 2014 at 19:17 Comment(3)
If it's packed, the field may not be properly aligned.Ventriculus
@T.C.: Is there a way to tell gcc "Screw alignment, I am on x86"?Gabriellia
@Gabriellia return (int*&)ptr;Incurvate
S
5

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.

Stocky answered 15/12, 2014 at 19:21 Comment(10)
Don't believe this, just found the same bug report and was about to post the exact same quote...Chimkent
I tried the workaround with the alginment attribute. It is simply ignored by my gcc.Gabriellia
@Gabriellia The "workaround" looks like a hack that avoids the error message but doesn't actually work. Have getPtr return a proxy instead.Incurvate
@MarcGlisse: What do you mean with proxy here?Gabriellia
@Gabriellia an object that internally stores Foo* and allows manipulation of the ptr field.Ticklish
en.wikibooks.org/wiki/More_C++_Idioms/Temporary_Proxy (or whatever else google comes up with), see vector<bool>::operator[] for an example.Incurvate
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.Venetis
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.Undressed
@DanQ Can you elaborate? How is accessing the address the pointer points to any different than using the reference?Berserk
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.Undressed

© 2022 - 2024 — McMap. All rights reserved.