C 2018 6.5.9 обсуждается ==
.Параграф 2 определяет ограничения, а (void *) ptr == ptr
удовлетворяет ограничениям, потому что один из параметров - «один операнд является указателем на тип объекта, а другой - указателем на квалифицированную или неквалифицированную версию void
».Затем в параграфе 5 говорится: «… Если один операнд является указателем на тип объекта, а другой - указателем на квалифицированную или неквалифицированную версию void, первый преобразуется в тип последнего».
Таким образомв (void *) ptr == ptr
правый операнд преобразуется в (void *)
, поэтому выражение эквивалентно (void *) ptr == (void *) ptr
, и мы можем ожидать, что оно оценивается как true.
Строго говоря, предложение о преобразовании указателя,6.3.2.3, говорит нам только, что результат преобразования (void *) ptr
обратно в исходный тип будет сравниваться равным ptr
.Он ничего не говорит нам о значении (void *) ptr
, и поэтому, рассматривая только этот пункт, возможно, что два разных экземпляра (void *) ptr
будут давать разные результаты, если они содержат достаточно информации, чтобы произвести что-то, чтобудет сравниваться равным исходному ptr
при обратном преобразовании.
Возвращаясь к 6.5.9, параграф 6 говорит нам:
Два указателя сравнивают равные, если и только если оба равны нулюуказатели, оба являются указателями на один и тот же объект (включая указатель на объект и подобъект в его начале) или функцию, оба являются указателями на один после последнего элемента того же объекта массива, или один - указатель на один послеконец одного объекта массива, а другой - указатель на начало другого объекта массива, который сразу же следует за первым объектом массива в адресном пространстве.
Теперь, конечно, мы ожидаем (void *) ptr == (void *) ptr
чтобы быть правдой, по крайней мере, иногда.Как это возможно?(void *) ptr
не является нулевым указателем (при условии, что ptr
не было), и при этом мы не ожидаем, что этот случай покрывается концом одного массива и началом другого случая.Таким образом, мы ожидаем, что, когда (void *) ptr == (void *) ptr
оценивается как true, это должно быть потому, что он находится в случае «указатели на один и тот же объект» или «указатели на один после последнего элемента того же самого случая объекта массива».Это кажется единственным разумным способом интерпретации стандарта.Если это так, то этот случай (в зависимости от того, который применяется иногда) должен применяться постоянно, и «если и только если» говорит нам, что (void *) ptr == (void *) ptr
всегда верно.