Вместо того, чтобы пытаться указать все гарантии, которые должны поддерживаться качественными реализациями на обычных платформах, Стандарт вместо этого стремится избегать предоставления каких-либо гарантий, которые могут быть дорогостоящими или проблематичными для любой мыслимой платформы, если только они не настолько ценны, чтобы оправдать какие-либовозможная стоимость.Авторы ожидали (разумно в то время), что качественные компиляторы для платформ, которые могли бы предложить более сильные гарантии практически без затрат, сделали бы это, и, таким образом, увидели необходимость явно предписывать действия, которые компиляторы собирались делать в любом случае.
Если одинПосмотрите на то, что на самом деле гарантия, предлагаемая стандартом, это абсурдно глупо.Он указывает, что преобразование void * в uintptr_t и затем обратно в void * даст указатель, который можно сравнить с оригиналом, и что сравнение сообщит, что два указателя равны.Он ничего не говорит о том, что произойдет, если код сделает что-то еще с указателем, преобразованным в оба конца.Соответствующая реализация может выполнять преобразования целочисленных указателей таким образом, что игнорируется целочисленное значение (если только это не нулевая указатель-константа) и получается некоторый произвольный битовый шаблон, который не соответствует ни одному действительному или нулевому указателю, а затем иметь указательоператоры неравенства сообщают «равно» всякий раз, когда любой операнд содержит этот специальный битовый шаблон.Конечно, ни одна качественная реализация не должна вести себя таким образом, но ничто в Стандарте не запретило бы это.
В отсутствие оптимизации было бы разумно предположить, что на любой платформе, которая использует "линейные" указатели, которыетакого же размера, как и uintptr_t
, качественные компиляторы будут обрабатывать преобразование указателей в uintptr_t
таким образом, что преобразование равных указателей приведет к тому же числовому значению, а значение uintptr_t u;
, если u==(uintptr)&someObject
, то *(typeOfObject*)u
можетиспользоваться для доступа к someObject
, по крайней мере, между моментом, когда адрес someObject
был преобразован в uintptr_t
, и в следующий раз, когда к someObject
обращаются другими способами, независимо от того, как u
стал удерживать егозначение.К сожалению, некоторые компиляторы слишком примитивны, чтобы признать, что преобразование адреса в uintptr_t
предполагает, что указатель, сформированный из uintptr_t
, может идентифицировать тот же объект.