C 2018 6.5.9 обсуждает ==
. Параграф 2 определяет ограничения, и (void *) ptr == ptr
удовлетворяет ограничениям, потому что один из вариантов - «один операнд является указателем на тип объекта, а другой - указателем на квалифицированную или неквалифицированную версию void
». Затем в параграфе 5 говорится: «… Если один операнд является указателем на тип объекта, а другой - указателем на квалифицированную или неквалифицированную версию void, первый преобразуется в тип второго».
Таким образом, в (void *) ptr == ptr
правый операнд преобразуется в (void *)
, поэтому выражение эквивалентно (void *) ptr == (void *) ptr
, и мы можем ожидать, что оно будет истинным.
Строго говоря, пункт 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
оценивается как истинное, это должно быть потому, что оно находится в случае «указатели на тот же объект» или «указатели на один за последним элементом того же случая объекта массива». Это кажется единственным разумным способом интерпретации стандарта. Если это так, то этот случай (какой бы из них ни применялся иногда) должен применяться постоянно, а «если и только если» говорит нам, что (void *) ptr == (void *) ptr
всегда верно.
person
Eric Postpischil
schedule
09.06.2019
(void*) ptr == ptr
то же самое, что и(void*) ptr == (void*) ptr
, потому что второй операнд будет неявно преобразован вvoid*
для проведения сравнения. Хотя не уверен на 100% ... - person Nikos C.   schedule 09.06.2019ptr
не является указателем на функцию, и в этом случае стандарт не гарантирует этого. - person Tom Karzes   schedule 09.06.2019