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 для приведения указателей.
Просто включите предупреждения компилятора - он скажет (или должен) сказать вам, что небезопасно.