Каковы ограничения в сравнении двух указателей?
int a=40,b=34;
int *iptr1,*iptr2;
iptr1 = &a;
iptr2 = &b;
printf("\n Equal condition of two pointers=%d", (ip1 == ip2)); //no error
char name1[20], name2[20];
char *p1 = name1;
char *p2 = name2;
if(p1 > p2) /*Error*/
Почему есть ошибка / предупреждение для операции отношения, но нет для операции сравнения?
2 ответа
Вы можете выполнять только реляционные операции (<
, >
, <=
, >=
) на указатели из того же массива или того же агрегатного объекта. В противном случае это вызывает неопределенное поведение.
квотирование C11
глава §6.5.8, операторы отношений, параграф 5
Когда сравниваются два указателя, результат зависит от относительного расположения в адресном пространстве указанных объектов. Если два указателя на типы объектов оба указывают на один и тот же объект или оба указывают один за другим последний элемент одного и того же объекта массива, они сравниваются одинаково. Если указанные объекты являются членами одного и того же агрегатного объекта, указатели на элементы структуры, объявленные позже, сравниваются больше, чем указатели на элементы, объявленные ранее в структуре, а указатели на элементы массива с большими значениями нижнего индекса сравниваются больше, чем указатели, на элементы того же массива с более низкими значениями индекса. Все указатели на члены одного и того же объекта объединения сравниваются одинаково. Если выражение
P
указывает на элемент объекта массива и выражениеQ
указывает на последний элемент того же объекта массива, выражение указателяQ+1
сравнивает больше чемP
, Во всех остальных случаях поведение не определено.
В вашем коде
if(p1>p2)
попытка сравнить два указателя, которые не являются частью одного и того же объекта массива, и не являются членами одного и того же агрегатного объекта. Таким образом, это вызывает предупреждение.
Однако для сравнения такое ограничение не сохраняется, поэтому выражение типа (ip1==ip2)
совершенно нормально.
Вы можете сравнить указатели с операторами равенства (==
или же !=
) которые указывают на разные объекты или элементы разных массивов. Если указатели не указывают на один и тот же объект, они считаются неравными.
Точнее (Стандарт C, 6.5.9 Операторы равенства)
6 Два указателя сравниваются равными, если и только если оба являются нулевыми указателями, оба являются указателями на один и тот же объект (включая указатель на объект и подобъект в его начале) или на функцию, оба являются указателями на один после последнего элемента того же объект массива, или один - указатель на один конец конца одного объекта массива, а другой - указатель на начало другого объекта массива, который непосредственно следует за первым объектом массива в адресном пространстве.
Рассмотрим следующий пример.
#include <stdio.h>
int main(void)
{
struct A
{
int x;
int y;
} a;
printf( "&a.x + 1 == &a.y is %d\n", &a.x + 1 == &a.y );
return 0;
}
Если между элементами данных нет заполнения x
а также y
структуры, то выход будет равен 1
потому что каждый элемент данных может рассматриваться как массив с одним элементом и "массив" y
сразу следует за "массивом" x
,
Однако вы не можете сравнивать указатели с реляционными операторами (<
, >
, <=
, >=
), которые не указывают на элементы одного и того же массива или после конца одного и того же массива.