Почему я не могу вернуть ссылку на упакованное поле?

Я использую g++ для компиляции кода с упакованными полями. Однако я получаю сообщение об ошибке при попытке вернуть ссылку на упакованное поле.

Пример:

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

выдает ошибку:

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

Почему я не могу вернуть ссылку на упакованное поле?


person gexicide    schedule 15.12.2014    source источник
comment
Если оно упаковано, поле может быть неправильно выровнено.   -  person T.C.    schedule 15.12.2014
comment
@TC: Есть ли способ определить выравнивание gcc Screw, я на x86?   -  person gexicide    schedule 15.12.2014
comment
@gexicide return (int*&)ptr;   -  person Marc Glisse    schedule 16.12.2014


Ответы (1)


Существует отчет об ошибке gcc Не удается связать упакованное поле, который охватывает это и он говорит:

В спецификации C++ (C++03, разделы 3.9, 3.9.1, 3.9.2) очень ясно указано, что T и указатель на T имеют требования к выравниванию, зависящие от реализации. Если у вас есть указатель на T, вы можете предположить, что он соответствует требованиям выравнивания. Я уверен, что спецификация C имеет аналогичный язык.

В случае ОП следующий код может нарушить требования выравнивания.

Они предлагают обходной путь, используя атрибут alignment для определения вашего собственного выровненного типа, но похоже, что он не работает.

person Shafik Yaghmour    schedule 15.12.2014
comment
Не верьте, только что нашел тот же отчет об ошибке и собирался опубликовать точно такую ​​же цитату... - person Columbo; 15.12.2014
comment
Я попробовал обходной путь с атрибутом alginment. Он просто игнорируется моим gcc. - person gexicide; 15.12.2014
comment
@gexicide Обходной путь выглядит как хак, который позволяет избежать сообщения об ошибке, но на самом деле не работает. Вместо этого пусть getPtr вернет прокси. - person Marc Glisse; 15.12.2014
comment
@MarcGlisse: Что вы имеете в виду под прокси? - person gexicide; 15.12.2014
comment
@gexicide объект, который внутренне хранит Foo* и позволяет манипулировать полем ptr. - person rightfold; 15.12.2014
comment
en.wikibooks.org/wiki/More_C++_Idioms/Temporary_Proxy ( или что-то еще, что предлагает Google), см. пример vector<bool>::operator[]. - person Marc Glisse; 15.12.2014
comment
Если у меня может быть указатель на поле пакета, почему у меня не может быть ссылки на упакованное поле? Адрес члена известен в обоих случаях. - person Nuclear; 30.03.2015
comment
Поскольку не все платформы поддерживают память с байтовой адресацией, и возврат невыровненной структуры вызовет ошибку сегментации во время выполнения при доступе к возвращаемому значению. - person Dan; 24.04.2018
comment
@DanQ Можете ли вы уточнить? Чем отличается доступ к адресу, на который указывает указатель, от использования ссылки? - person jterm; 07.09.2018
comment
В архитектурах, которые не адресуются по байтам, компилятор по-прежнему позволяет вам получать доступ к невыровненным полям, выполняя преобразования памяти за кулисами (например, маскирование и сдвиг), чтобы получить желаемое значение. Это известно только потому, что структура упакована во время компиляции. Если компилятор потеряет эту упакованную информацию, он может попытаться получить прямой доступ к неподдерживаемой ячейке памяти, что вызовет серьезную ошибку. Несмотря на то, что в вопросе OP это не имеет значения, GCC не рискует и запрещает операцию. - person Dan; 07.09.2018