Насколько я понимаю, GCC поддерживает все свои функции C99 в C++. Но как строгое искажение C99 обрабатывается в коде C++?
Я знаю, что кастинг с бросками C между несвязанными типами не является strict-aliasing-safe и может сгенерировать неправильный код, но что относительно C++? Так как строгое искажение не является частью стандарта C++ (который корректен?), GCC должен указывать саму семантику.
Я фигурирую const_cast
и static_cast
бросок между связанными типами, следовательно они безопасны, в то время как reinterpret_cast
может нарушить строгие правила искажения.
Действительно ли это - корректное понимание?
Нет, вы, вероятно, смешиваете разные вещи.
Строгие правила псевдонима не имеют абсолютно ничего общего со стандартом C99. Строгие правила псевдонима уходят корнями в те части стандарта, которые присутствовали в C и C ++ с начала [стандартизованных] времен. Предложение, запрещающее доступ к объекту одного типа через lvalue другого типа, присутствует в C89 / 90 ( 6.3 ), а также в C ++ 98 ( 3.10 / 15 ). Вот в чем суть строгого псевдонима, ни больше, ни меньше. Просто не все компиляторы хотели (или осмелились) применять его или полагаться на него. И C, и C ++ языки иногда используются как языки «сборки высокого уровня», и строгие правила псевдонима часто мешают такому использованию. Это был GCC, который сделал этот смелый шаг и решил начать полагаться на строгие правила псевдонима при оптимизации, часто вызывая жалобы от этих «сборочных» типов.
Это правда, что самый простой способ нарушить строгие правила псевдонима в C ++ - это reinterpret_cast
(и, конечно же, приведение в стиле C). Однако для этой цели также можно использовать static_cast
, поскольку он позволяет нарушить строгий псевдоним, используя void *
в качестве промежуточного типа в «цепочечном» приведении
int *pi;
...
double *pd = static_cast<double *>(static_cast<void *>(pi));
const_cast
не может нарушить строгий псевдоним в совместимом компиляторе.
Что касается C99 ... В C99 был введен квалификатор restrict
. Это напрямую связано с псевдонимом, но не само по себе так называемым строгим псевдонимом.
В Cpp концепция та же; в том смысле, что вы можете использовать касты в стиле C, чтобы направлять вас через то, что считается безопасным в отношении строгого алиасинга.
Короче говоря: нет, подход к использованию приведения в Cpp (который вы описали) не будет безопасным для всех случаев. Один из распространенных способов нарушить правила - использовать static_cast для приведения указателей.
Просто включите предупреждения компилятора - он скажет (или, должен сказать) вам, что является небезопасным.
static_cast
также может нарушать правила псевдонима, потому что компилятор доверяет вам убедиться, что целевой тип связан с фактическим типом времени выполнения объекта. . Рассмотрим:
extern void f(double*, int*); // compiler may optimize assuming that arguments don't overlap
double d;
void* pv = &d;
int* pi = static_cast<int*>(pv);
f(&d, pi); // assumption is violated