Преобразование между long * и int *, когда sizeof (long) == sizeof (int)

Мы знаем в общем sizeof(long) != sizeof(int), Но какие части стандарта (C ++ 11) запрещают использование псевдонимов long* через int*? Является ли это просто упущением в [conv.ptr], правилами наложения имен в [basic.lval] или чем-то еще?

void f()
{
static_assert(sizeof(int) == sizeof(long), "");
long x[] = {1, 2};
int* y = x; // error: invalid conversion from ‘long int*’ to ‘int*’ [-fpermissive]
}

2

Решение

Да, это бездействие в [conv.ptr] и соответствующий пункт в [expr.reinterpret.cast],

7 Указатель объекта может быть явно преобразован в указатель объекта
другой тип. Когда значение v типа «указатель на T1»
преобразован в тип «указатель на cv T2», результат
static_cast<cv T2*>(static_cast<cv void*>(v)) если оба T1 и T2
Типы стандартного макета (3.9) и требования выравнивания T2
не более строгие, чем у T1, или если любой из типов является недействительным. Преобразование
prvalue типа «указатель на T1» на тип «указатель на T2» (где T1
и T2 являются типами объектов, и где требования выравнивания T2
не более строгие, чем у T1), и обратно в исходный тип дает
исходное значение указателя. Результат любого другого такого указателя
конверсия не указана.

Вы должны использовать reinterpret_cast<int*>(...),


РЕДАКТИРОВАТЬ. В комментариях есть беспокойство, которое я делаю более заметным в этом редакторе, что это не вопрос языка-юриста, а намерение использовать указатель. Я не уверен, как возникла проблема, так как довольно очевидно, что можно просто C-cast без вопросов, но если есть сомнения — указатель приведен к int* нарушает строгое наложение правила.

То есть неопределенное поведение может возникать из-за того, что вы нарушаете предположение компилятора о том, что указатели разных типов никогда не могут указывать на одну и ту же область памяти.

0

Другие решения

long а также int два разных типа, даже если они имеют одинаковый размер, поэтому я думаю, что неправильное преобразование связано с [basic.lval.10]

Если программа пытается получить доступ к сохраненному значению объекта через
поведение, отличное от одного из следующих типов поведения
не определено:

  • динамический тип объекта,
  • cv-квалифицированная версия динамического типа объекта,
  • тип, подобный (как определено в 4.4) динамическому типу объекта,
  • тип, который является типом со знаком или без знака, соответствующим динамическому типу
    объект,
  • тип, который является типом со знаком или без знака, соответствующим cv-квалифицированной версии динамического типа объекта,
  • агрегатный или объединенный тип, который включает в себя один из вышеупомянутых типов
    среди его элементов или нестатических членов данных (в том числе,
    рекурсивно, элемент или нестатический член данных субагрегата или
    содержавший союз),
  • тип, который является (возможно, квалифицированным cv) типом базового класса динамического типа объекта,
  • тип char или unsigned char.

Как примечание стороны, если [basic.lval] не существовало, были бы другие проблемы: один и тот же размер не означает одинаковое представление / диапазон.

Там нет никакой гарантии, что значение битов в int точно соответствуют значениям битов в long,

0

По вопросам рекламы [email protected]