Стандарт не требует, чтобы реализации обрабатывали преобразования целочисленных значений в указатели осмысленным образом для любых конкретных целочисленных значений или даже для любых возможных целочисленных значений, отличных от констант нулевых указателей. Единственное, что он гарантирует в отношении таких преобразований, - это то, что программа, которая сохраняет результат такого преобразования непосредственно в объект подходящего типа указателя и ничего с этим не делает, за исключением проверки байтов этого объекта, в худшем случае увидит неопределенные значения. Хотя поведение преобразования целого числа в указатель определяется реализацией, ничто не помешает любой реализации (независимо от того, что она на самом деле делает с такими преобразованиями!) От указания того, что некоторые (или даже все) байты для представления, имеющего значения Unspecified и указывающего, что некоторые (или даже все) целочисленные значения могут вести себя так, как будто они дают представления ловушек.
Единственные причины, по которым Стандарт вообще что-либо говорит о преобразованиях целых в указатель, заключаются в том, что:
В некоторых реализациях конструкция имеет смысл, и некоторые программы для этих реализаций требуют этого.
Авторам Стандарта не понравилась идея, что конструкция, которая использовалась в некоторых реализациях, представляла бы нарушение ограничений для других.
Было бы странно, если бы Стандарт описал конструкцию, но затем указал, что она имеет неопределенное поведение во всех случаях.
Лично я считаю, что Стандарт должен был позволять реализациям рассматривать преобразования целых чисел в указатели как нарушения ограничений, если они не определяют ситуации, в которых они были бы полезны, вместо того, чтобы требовать, чтобы компиляторы принимали бессмысленный код, но это не была философия в то время.
Я думаю, что было бы проще сказать, что любая операция, включающая в себя преобразования целочисленных значений в указатели с любыми значениями, отличными от значений intptr_t или uintptr_t, полученных из преобразований указателей в целые числа, вызывает неопределенное поведение, но затем следует отметить, что оно является общим для качественные реализации, предназначенные для низкоуровневого программирования для обработки неопределенного поведения «документированным образом, характерным для окружающей среды». Стандарт не определяет, когда реализации должны обрабатывать программы, которые вызывают UB таким образом, а вместо этого рассматривает это как проблему качества реализации.
Если реализация указывает, что преобразования целых чисел в указатели работают таким образом, который определяет поведение
char *p = (char*)1;
p++;
как эквивалент "char p = (char ) 2;", тогда реализация должна работать именно так. С другой стороны, реализация может определять поведение преобразования целых чисел в указатель таким образом, чтобы даже:
char *p = (char*)1;
char *q = p; // Not doing any arithmetic here--just a simple assignment
выпустит носовых демонов. На большинстве платформ компилятор, в котором арифметика указателей, полученных при преобразованиях целых чисел в указатель, ведет себя странно, не будет рассматриваться как высококачественная реализация, подходящая для низкоуровневого программирования. Таким образом, программист, который не намерен нацеливаться на какие-либо другие реализации, может ожидать, что такие конструкции будут вести себя с пользой на компиляторах, для которых подходит код, даже если стандарт не требует этого.