C99 строгое искажение управляет в C++ (GCC)

Насколько я понимаю, GCC поддерживает все свои функции C99 в C++. Но как строгое искажение C99 обрабатывается в коде C++?

Я знаю, что кастинг с бросками C между несвязанными типами не является strict-aliasing-safe и может сгенерировать неправильный код, но что относительно C++? Так как строгое искажение не является частью стандарта C++ (который корректен?), GCC должен указывать саму семантику.

Я фигурирую const_cast и static_cast бросок между связанными типами, следовательно они безопасны, в то время как reinterpret_cast может нарушить строгие правила искажения.

Действительно ли это - корректное понимание?

18
задан Alex B 5 May 2010 в 06:25
поделиться

3 ответа

Нет, вы, вероятно, смешиваете разные вещи.

Строгие правила псевдонима не имеют абсолютно ничего общего со стандартом 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 . Это напрямую связано с псевдонимом, но не само по себе так называемым строгим псевдонимом.

31
ответ дан 30 November 2019 в 07:22
поделиться

В Cpp концепция та же; в том смысле, что вы можете использовать касты в стиле C, чтобы направлять вас через то, что считается безопасным в отношении строгого алиасинга.

Короче говоря: нет, подход к использованию приведения в Cpp (который вы описали) не будет безопасным для всех случаев. Один из распространенных способов нарушить правила - использовать static_cast для приведения указателей.

Просто включите предупреждения компилятора - он скажет (или, должен сказать) вам, что является небезопасным.

2
ответ дан 30 November 2019 в 07:22
поделиться

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
4
ответ дан 30 November 2019 в 07:22
поделиться