Проверяя ссылки для другого вопроса, я заметил странное предложение в C ++ 11 по адресу [expr.rel] ¶3:
Указатели на
void
(после преобразований указателей) можно сравнивать с результатом, определяемым следующим образом: если оба указателя представляют один и тот же адрес или оба являются значениями нулевого указателя, результатом будетtrue
, если оператор<=
или>=
, иfalse
в противном случае; в противном случае результат не указан.
Похоже, это означает, что после того, как два указателя были преобразованы в void *
, их отношение упорядочения больше не гарантируется; например, это:
int foo[] = {1, 2, 3, 4, 5};
void *a = &foo[0];
void *b = &foo[1];
std::cout<<(a < b);
казалось бы, не указано.
Интересно, что этого предложения не было в C ++ 03 и исчезло в C ++ 14, поэтому, если мы возьмем приведенный выше пример и применим к нему формулировку C ++ 14, я бы сказал, что ¶3.1
- Если два указателя указывают на разные элементы одного и того же массива или на его подобъекты, указатель на элемент с более высоким нижним индексом сравнивается с большим.
будет применяться, поскольку a
и b
указывают на элементы одного и того же массива, даже если они были преобразованы в void *
. Обратите внимание, что формулировка ¶3.1 была почти такой же в C ++ 11, но, похоже, была отменена предложением void *
.
Прав ли я в своем понимании? Какой смысл в этом странном предложении, добавленном в C ++ 11 и немедленно удаленном? Или, может быть, он все еще там, но перемещен в / подразумевается какой-то другой частью стандарта?
void *
, поэтому явное преобразование не требуется, хотя верно, что на некоторых нечетных архитектурах (на ум приходит сегментированная память) преобразование вvoid *
может не быть простой побитовой копией; тем не менее, я не могу представить архитектуру, в которой обычный указатель на преобразование большогоvoid
указателя не сохранил бы отношения упорядочения между элементами одного и того же массива. - person Matteo Italia   schedule 25.01.2019void*
, посколькуvoid[]
нет. - person MSalters   schedule 25.01.2019a - b
будет реализован какint c; while((c = rand()) + b == a);
, но это не значит, что это хоть сколько-нибудь разумно. :-) Кроме того, я ожидал, что это нарушит требования временной сложности, указанные где-то в разделе алгоритмов / контейнеров. - person Matteo Italia   schedule 25.01.2019char c; bool b = (void *)&c == (void *)&c
было бы ложным вопреки всем причинам. Я правильно читаю? - person Peter - Reinstate Monica   schedule 25.01.2019<
,<=
,>=
,>
), операторы равенства обсуждаются в следующем разделе ([expr.eq]), что гарантирует что результат вашего выражения действительноtrue
(Два указателя одного типа сравниваются равными тогда и только тогда, когда они оба равны нулю, оба указывают на одну и ту же функцию или оба представляют один и тот же адрес (3.9.2). < / я>) - person Matteo Italia   schedule 25.01.2019x<=y
на voids имеет семантикуx==y||x<y
; если левая часть верна, то результат определенно верен и четко определен. Если левая часть ложна, значит, мы находимся на территории неопределенного поведения; нет никакой гарантии, что указатели void упорядочены каким-либо согласованным образом. Я считаю, что это еще одна ошибка; разработчик, который пишет<=
явно не имеет в голове ни равенства, ни УБ. - person Eric Lippert   schedule 25.01.2019