reinterpret_cast между понтером и встроенным типом разного размера

Что на самом деле происходит, когда мы делаем следующее:
1)

int i = -1; // 32 bit
void *p;
p = reinterpret_cast<void*>(i)

в 64-битной архитектуре sizeof (void *) == 8

2)

long long i; // 64 bit
void *p = (unsigned int)(-1);
i = retinterpret_cast<long long>(p)

на 32-битной архитектуре sizeof (void *) = 4

Я обычно понимаю, каков будет результат, но я хочу, чтобы кто-нибудь описал этот механизм в терминах стандарта C ++ для лучшего понимания.

Во втором случае поведение аналогично описанному в «интегральных продвижениях» (4.5) (я буду -1)
для случая «int — unsigned long», поэтому мы обычно говорим, что указатели преобразуются как целые числа со знаком?

3)

int i = ...;
unsigned long long L = ...;
i = L;

Какие правила применяются здесь?

4

Решение

Все преобразования между указателями и целочисленными типами
реализация определена. Единственная гарантия, которую стандарт делает
в том, что:

Значение целочисленного типа или типа перечисления может быть явно
преобразован в указатель Указатель, преобразованный в целое число
достаточный размер (если таковой существует в реализации) и
обратно к тому же типу указателя будет иметь свое первоначальное значение

Стандарт, однако, делает заявление (в
ненормативная справка), которая:

Это должно быть неудивительно для тех, кто знает
структура адресации базовой машины.

С точки зрения качества реализации, если машина
имеет линейную адресацию, int указатель должен
привести к значению, которое соответствует значению int, если
слово (независимо от его размера) рассматривается как целостный тип; в
Другими словами, битовый рисунок не изменился. Если интеграл
тип меньше и отрицательный, это открытый вопрос
должен быть расширен знак, или должны ли остальные биты
установить на 0. Я предпочитаю второе, но я думаю, что оба могут быть
считается «неудивительным».

С прагматической точки зрения: существует значительное количество
программное обеспечение там, которое будет время от времени бросать небольшой
неотрицательное целое значение void*и ожидает получить его
вернемся с актерами позже. Формально, чтобы получить его обратно, требуется
преобразование сначала в intptr_t (или больше); в противном случае код
не должен компилироваться. Но я не могу представить, чтобы компилятор сломал это
иначе. Для отрицательных значений, с другой стороны, я бы чувствовал
значительно менее уверен. И я не уверен, насколько маленький маленький,
или. (В настоящее время я использую технику в одном особом случае для
значения меньше, чем 40 или 50. Я работаю с MSC, G ++ и Sun
СиСи, по крайней мере, и я не могу себе представить, что это не сработает ни на одном другом
основные Unix-машины, которые я использовал в прошлом. Но я бы не стал
рассчитывать на это на 16-битной Intel, или некоторых других более экзотических
машины, которые я видел, и, конечно, не на встроенной системе.)

Наконец, что касается ваших точных вопросов: это может измениться. Я бы попробовал
и видите, рассчитывая на то, что все, что он делает, есть
какой-то код, который рассчитывает на то, что он делает это, и что
продавец не рискует изменить свое поведение. Формально, так как это
реализация определена, разработчик обязан документировать
это (и может, конечно, изменить его в следующей версии), но
Я вообще нашел это очень, очень трудно найти это
документация.

РЕДАКТИРОВАТЬ:

Я только заметил, что ваш последний вопрос касается unsigned long
long
в int, Это интегральное преобразование, а не
reinterpret_cast, поэтому применяются разные правила. Или скорее
правила указаны в другом разделе: основное правило
все еще «реализация определена»:

Если тип назначения подписан, значение не изменяется, если оно
может быть представлен в типе назначения (и битовом поле
ширина); в противном случае значение определяется реализацией.

Стандарт C здесь несколько иной, в том смысле, что он явно
позволяет повысить сигнал, определенный реализацией. (Это
несколько растягивая, чтобы сказать, что «значение» в C ++
Стандарт может быть повышение сигнала, даже если это будет
предпочтительная реализация.) На практике: все
компиляторы, которых я знаю, просто игнорируют дополнительные биты старшего разряда.

5

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

Поведение не определено. Все может случиться. Даже не гарантируется, что результат будет последовательным. reinterpret_cast<void*>(1) == reinterpret_cast<void*>(1) может быть false,

-1

По вопросам рекламы ammmcru@yandex.ru