C99 строгие правила псевдонимов в C++ (GCC)

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

Я знаю, что приведение с помощью C приведений между несвязанными типами не является безопасным для строгих псевдонимов и может генерировать неправильный код, но как насчет C++? Поскольку строгий псевдоним не является частью стандарта C++ (это правильно?), GCC должен сам определять семантику.

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

Это правильное понимание?

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 Классификатор. Это напрямую связано с псевдонимами, но это не так называемый строгий псевдоним.

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

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

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

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

Другие вопросы по тегам