Подтвердить что ты не робот

Это неуказанное поведение для сравнения указателей с разными массивами для равенства?

Операторы равенства имеют смысловые ограничения реляционных операторов на указатели:

Операторы == (равно) и a = = (не равные) имеют те же семантические ограничения, преобразования и тип результата, что и реляционные операторы, за исключением их более низкого приоритета и результата истины. [С++ 03 §5.10p2]

И реляционные операторы имеют ограничение на сравнение указателей:

Если два указателя p и q того же типа указывают на разные объекты, которые не являются членами одного и того же объекта или элементов одного и того же массива или с разными функциями или если только один из них является нулевым, результаты p < q, p > q, p <= q и p >= q не определены. [§5.9p2]

Является ли это семантическим ограничением, которое "унаследовано" операторами равенства?

В частности, данный:

int a[42];
int b[42];

Ясно, что (a + 3) (b + 3) неуказан, но является (a + 3) == (b + 3) также неуказанным?

4b9b3361

Ответ 1

Семантика для op== и op!= явно говорит о том, что отображение за исключением их результата истинной стоимости. Поэтому вам нужно посмотреть, что определено для результата их истинной ценности. Если они говорят, что результат неуточнен, то он не указан. Если они определяют конкретные правила, то это не так. В нем говорится, в частности,

Два указателя одинакового типа сравнивают одинаковые, если и только если оба они равны нулю, оба указывают на одну и ту же функцию или оба представляют один и тот же адрес

Ответ 2

Результат от операторов равенства (== и !=) дает заданные результаты, если указатели относятся к объектам того же типа. Учитывая два указателя на один и тот же тип, верно одно из следующих:

  • оба являются нулевыми указателями, и они сравниваются друг с другом.
  • оба являются указателями на один и тот же объект, и они сравниваются друг с другом.
  • они являются указателями на разные объекты, и они сравниваются неравномерно друг с другом.
  • по крайней мере один не инициализирован, и результат сравнения не определен (и, на самом деле, само сравнение никогда не произойдет - просто попытка прочитать указатель для сравнения дает поведение undefined).

При тех же ограничениях (оба указателя относятся к одному и тому же типу объекта) результат от операторов упорядочения (<, <=, >, >=) указывается только в том случае, если оба они являются указателями к одному и тому же объекту или для разделения объектов в одном массиве (и для этой цели "кусок" памяти, выделенной с помощью malloc, new и т.д., квалифицируется как массив). Если указатели относятся к отдельным объектам, которые не являются частью одного и того же массива, результат не указан. Если один или оба указателя не были инициализированы, у вас есть поведение undefined.

Тем не менее, шаблоны сравнения в стандартной библиотеке (std::less , std::greater, std::less_equal и std::greater_equal) все дают итоговый результат, даже если/если встроенные операторы не, В частности, они должны давать полное упорядочение. Таким образом, вы можете получить заказ, если хотите, просто не со встроенными операторами сравнения (хотя, конечно, если один или оба указателя не инициализированы, поведение по-прежнему undefined).

Ответ 3

Поскольку существует путаница в семантике соответствия, это правила для С++. C использует совершенно другую модель соответствия.

  • Undefined поведение является оксюмороническим термином, это означает, что переводчик НЕ ваша программа, может делать то, что ему нравится. Обычно это означает, что он может генерировать код, который также будет делать все, что угодно (но это вычет). Если в стандарте указано, что поведение undefined, текст фактически не имеет никакого значения для пользователя в том смысле, что возврат этого текста не изменит требования, которые Стандарт налагает на переводчиков.

  • Программа, созданная в соответствии со стандартами, означает, что если не указано иное, поведение переводчика жестко определено: требуется отклонить вашу программу и выпустить диагностическое сообщение. Основным частным случаем здесь является правило с одним определением, если вы нарушите, что ваша программа плохо сформирована, но не требуется диагностика.

  • Приведенная реализация накладывает на переводчика требование, чтобы он содержал документацию, явно указывающую поведение. В этом специальном случае undefined Поведение может быть результатом, но должно быть явно указано.

  • Unspecified - это глупый термин, который означает, что поведение происходит из набора. В этом смысле четко определенный - это особый случай, когда набор разрешенных видов поведения содержит только один элемент. Unspecified не требует документации, поэтому в некотором смысле это также означает то же, что и реализация, определенная без документации.

В целом, С++ Standard - это не языковой стандарт, он является моделью для языка Standard. Для создания реального стандарта вам необходимо подключить различные параметры. Самыми простыми из них являются ограничения, определенные реализацией.

В стандарте есть несколько глупых конфликтов, например, законный переводчик может отклонить каждую явно хорошую С++-программу на том основании, что вам необходимо предоставить функцию main(), но переводчик поддерживает только идентификаторы 1 символа, Эта проблема решена с помощью понятия QOI или качества выполнения. В основном он говорит, кто заботится, никто не собирается покупать этот компилятор только потому, что он соответствует.

Технически неопределенный характер operator <, когда указатели относятся к несвязанным объектам, вероятно, означает: вы получите какой-то результат, который является либо истинным, либо ложным, но ваша программа не будет разбиваться, однако это неверно значение неопределенного, так что это дефект: неуказанный налагает нагрузку на авторов стандартов для документирования набора разрешенных поведений, потому что если набор открыт, то он эквивалентен поведению undefined.

Я фактически предложил std::less как решение проблемы, что некоторые структуры данных требуют, чтобы ключи были полностью упорядочены, но указатели не полностью упорядочены с помощью operator <. На большинстве машин с использованием линейной адресации less совпадает с <, но операция less, напр., Процессор x86 потенциально более дорогая.