Сравнение сравнений указателей с разными объектами

Вдохновленный этим ответом на этот вопрос , я немного вникнул в стандарты C11 и C99 для использования операторов равенства в указателях (исходный вопрос касается реляционных операторов). Вот что должен сказать C11 (C99 аналогичен) в § 6.5.9.6:

Два указателя сравнивают одинаковые, если и только если оба являются нулевыми указателями, оба являются указателями на один и тот же объект (включая указатель на объект и подобъект в начале) или функцию, оба являются указателями на один последний элемент одного и того же массива объект, или один – указатель на один конец конца одного объекта массива, а другой – указатель на начало другого объекта массива, который происходит сразу после первого объекта массива в адресном пространстве. 94 )

В сноске 94 говорится (и обратите внимание, что сноски являются ненормативными):

Два объекта могут быть смежными в памяти, поскольку они являются смежными элементами более крупного массива или смежных элементов структуры без прокладки между ними или потому, что реализация выбрала их так, даже если они не связаны. Если ранее недействительные операции указателя (такие как доступ к границам внешнего массива) приводили к неопределенному поведению, последующие сравнения также вызывают неопределенное поведение.

Текст текста и ненормативная записка, похоже, находятся в конфликте. Если серьезно воспринимать «если и только если» из текста текста, то в других обстоятельствах, кроме тех, которые указаны, должно быть возвращено равенство, и нет места для UB. Так, например, этот код:

uintptr_t a = 1; uintptr_t b = 1; void *ap = (void *)a; void *bp = (void *)b; printf ("%d\n", ap <= bp); /* UB by §6.5.8.5 */ printf ("%d\n", ap < bp); /* UB by §6.5.8.5 */ printf ("%d\n", ap == bp); /* false by §6.5.9.6 ?? */ 

должен печатать ноль, так как ap и bp являются указателями на один и тот же объект или функцию или любой из остальных бит.

В § 6.5.8.5 (реляционные операторы) поведение более ясно (мой акцент):

Когда сравниваются два указателя, результат зависит от относительных местоположений в адресном пространстве объектов, на которые указывает. Если два указателя на объект или неполные типы указывают на один и тот же объект или оба указывают один за последним элементом одного и того же объекта массива, они сравнивают равные. Если объекты, на которые указывают, являются членами одного и того же совокупного объекта, указатели на элементы структуры, объявленные позже, сравниваются больше, чем указатели на элементы, объявленные ранее в структуре, а указатели на элементы массива с большими значениями индекса сравниваются больше, чем указатели на элементы одного и того же массива с нижними значениями индекса. Все указатели на члены одного и того же объекта объединения сравниваются одинаково. Если выражение P указывает на элемент объекта массива, а выражение Q указывает на последний элемент одного и того же объекта массива, выражение указателя Q+1 сравнивается больше, чем P Во всех остальных случаях поведение не определено.

Вопросы:

  • Я верю, что существует некоторая двусмысленность в отношении того, что операторы равенства с указателями разрешены UB (сравнивая сноску и тело текста)?

  • Если нет двусмысленности, когда точно может быть сопоставление указателей с операторами равенства UB? Например, всегда ли UB, если по крайней мере один указатель искусственно создан (согласно выше)? Что, если один указатель ссылается на память, которая была free()d ? Учитывая, что сноска является ненормативной, можно ли заключить, что никогда не существует UB, в том смысле, что все «другие» сравнения должны давать false ?

  • Действительно ли § 6.5.9.6 означает, что сравнение равенства бессмысленных, но поразрядных равных указателей всегда должно быть ложным?

Обратите внимание, что этот вопрос отмечен как язык-юрист ; Я не спрашиваю, что на самом деле делают компиляторы, поскольку я считаю, что уже знаю ответ на этот вопрос (сравните их, используя тот же метод, что и сравнение целых чисел).

Правильно ли я утверждаю, что существует некоторая двусмысленность относительно того, когда операторы равенства с указателями являются UB?

Нет, потому что этот отрывок из п. 6.5.9 (3):

Операторы == и != Аналогичны реляционным операторам, за исключением их более низкого приоритета.

Полагает, что из условий § 6.9.9 (6) также применимы следующие операторы равенства:

Когда сравниваются два указателя […] Во всех остальных случаях поведение не определено.

Если нет двусмысленности, когда точно может быть сопоставление указателей с операторами равенства UB?

Существует неопределенное поведение во всех случаях, для которых стандарт явно не определяет поведение.

Всегда ли UB, если хотя бы один указатель искусственно созданный преобразован из произвольного целого числа?

§6.3.2.3 (5):

Целое число может быть преобразовано в любой тип указателя. За исключением, как указано ранее, результат определяется реализацией, может быть неправильно выровнен, может не указывать на объект ссылочного типа и может быть ловушечным представлением.

Что, если один указатель ссылается на память, free d?

§6.2.4 (2):

Значение указателя становится неопределенным, когда объект, на который он указывает, достигает конца своего срока службы.

можно ли заключить, что никогда не существует UB, в том смысле, что все «другие» сравнения должны давать ложные значения?

Нет. Стандарт определяет, при каких условиях два указателя должны сравнивать равные и при каких условиях два указателя должны сравнивать не равные. Любое сравнение равенств между двумя указателями, которое выходит за пределы обоих этих двух наборов условий, вызывает неопределенное поведение.

Действительно ли §6.5.9 (6) означает, что сравнение равенства бессмысленных, но поразрядных равных указателей всегда должно быть ложным?

Нет, это не определено.