Подтвердить что ты не робот

Void * с static_cast vs intptr_t с reinterpret_cast

Я хочу знать, существуют ли специфические, основанные на стандартах различия между двумя разными типами отливок очень конкретных типов. В частности, данный: type T и переменная T * object:

intptr_t opaque = reinterpret_cast<intptr_t>( object );
T * result = reinterpret_cast<T*>( opaque );

эквивалентно:

void * opaque = static_cast<void*>( object );
T * result = static_cast<T*>( opaque );

Мне больше всего нравится result, гарантировано ли это одно значение, эквивалентное оригиналу object для любого типа T? Мне все равно, какой бит-шаблон имеет промежуточный opaque, так как я считаю, что стандарт технически позволяет им быть разными в каждом случае (хотя никакой разумный компилятор не имел бы разных результатов).

Заметьте, меня не интересует общий случай static_cast vs. reinterpret_cast, который я хорошо понимаю. Меня интересует вышеупомянутый очень конкретный случай - в результате стандартного назначения специальной логики для static_cast и void*, которые делают его похожим на reinterpret_cast. (Есть несколько связанных вопросов по StackOverflow, но они более общие, и мой сценарий, я считаю, очень специфичен)

Стиль и предпочтение в стороне, есть ли какая-либо техническая причина, по которой одна форма должна использоваться над концом? Или гарантируется, что для всех T будет создана одна и та же конечная переменная result?

4b9b3361

Ответ 1

Да, оба гарантируют восстановление исходного значения указателя.

Первый задается С++ 11 5.2.10/5:

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

Второе задается С++ 11 5.2.9/13:

Значение указателя типа к объекту преобразованный в "указатель на cv void" и обратно, возможно с другой cv-квалификацией, должен иметь свой оригинал значение.

Существует техническая причина, чтобы предпочесть вторую версию по сравнению с первой: intptr_t является необязательным, но каждая реализация имеет void*.