В этой статье упоминается следующее относительно reinterpret_cast целых чисел и указателей:

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

Правильно ли я понимаю, что в этом случае стандарт не гарантирует следующее:

intptr_t x = 5; 
void* y = reinterpret_cast<void*>(x);
assert(x == reinterpret_cast<intptr_t>(y));

Может кто-нибудь подтвердить?

4
zse 31 Дек 2017 в 20:28

2 ответа

Лучший ответ

Ваша интерпретация верна. Соответствующий параграф стандарта - [expr.reinterpret.cast] / 5 в C ++ 17:

Значение целочисленного типа или типа перечисления может быть явно преобразовано в указатель. Указатель преобразован в целое число достаточного размера (если такое существует в реализации) и обратно к тому же типу указателя будет иметь первоначальное значение; сопоставления между указателями и целыми числами в противном случае определяются реализацией. [ Примечание . За исключением случаев, описанных в 6.7.4.3, результатом такого преобразования не будет указатель, полученный безопасно. стоимость. - конец примечания ]

Таким образом, в то время как отображение указателей на целые числа гарантированно имеет левый обратный (и, следовательно, инъективный), нет гарантии, что оно биективно; независимо от того, является ли это частью поведения, «определяемого реализацией». Как указывает cppreference, может быть несколько целых чисел, которые преобразуются в один и тот же указатель.

3
Brian 31 Дек 2017 в 17:34

Не может быть интегрального типа, который точно соответствует ширине адресного пространства платформы. intptr_t должен быть достаточно большим, чтобы вместить любое значение указателя, то есть он должен быть таким же большим или больше, чем указатель, а когда он больше, принцип «голубятни» гарантирует, что для каждого целочисленного значения невозможно иметь уникальное значение void*.

0
Ben Voigt 1 Янв 2018 в 22:39