Строгий псевдоним указателя: является ли доступ через «изменчивый» указатель / ссылку решением? - PullRequest
8 голосов
/ 05 июня 2010

По пятам конкретная проблема , ответ на свой вопрос и комментарии к нему, я хотел бы понять, если это правильное решение, обходной путь / хак или просто неправильно.

В частности, я переписал код:

T x = ...;
if (*reinterpret_cast <int*> (&x) == 0)
  ...

Как:

T x = ...;
if (*reinterpret_cast <volatile int*> (&x) == 0)
  ...

с указателем volatile на указатель.

Давайте просто предположим, что трактовать T как int в моей ситуации имеет смысл. Решает ли это доступ через ссылку volatile к решению проблемы наложения указателя?

Для справки, из спецификации:

[Примечание: volatile является подсказкой для реализации, чтобы избежать агрессивного оптимизация с участием объекта, потому что значение объекта может может быть изменен средствами, которые невозможно обнаружить реализацией. Смотрите 1.9 для подробная семантика. В общем, семантика volatile предназначена быть таким же в C ++, как и в C. - конец примечания]

EDIT:

Приведенный выше код решил мою проблему по крайней мере на GCC 4.5.

Ответы [ 2 ]

16 голосов
/ 05 июня 2010

Volatile не может помочь вам избежать неопределенного поведения здесь. Так что, если это работает для вас с GCC, это удача.

Давайте предположим, что T - это POD. Тогда правильный способ сделать это -

T x = …;
int i;
memcpy(&i,&x,sizeof i);
if (i==0)
  …

Там! Нет строгих проблем с псевдонимами и проблем с выравниванием памяти. GCC даже обрабатывает memcpy как встроенную функцию (в этом случае вызов функции не вставляется).

0 голосов
/ 15 июля 2012

Volatile не может помочь вам избежать неопределенного поведения здесь.

Что-нибудь относительно volatile несколько неясно в стандарте. Я в основном согласился с вашим ответом, но теперь я хотел бы немного не согласиться.

Чтобы понять, что означает volatile, стандарт не понятен большинству людей, особенно некоторым авторам компиляторов. Лучше подумать при использовании volatile (и только когда) C / C ++ в значительной степени является сборкой высокого уровня .

При записи в volatile lvalue компилятор выдаст STORE или множественный STORE, если одного недостаточно (volatile не подразумевает атомарный).

При записи в volatile lvalue компилятор выдаст ЗАГРУЗКУ или многократную ЗАГРУЗКУ, если ее недостаточно.

Конечно, там, где нет явных LOAD или STORE, компилятор просто выдаст инструкции, которые подразумевают LOAD или STORE.

Sellibitze дал лучшее решение: используйте memcpy для реинтерпретации битов.

Но если все обращения к области памяти осуществляются с volatile lvalues, совершенно ясно, что строгие правила псевдонимов не применяются . Это ответ на ваш вопрос.

...