Каковы ограничения в сравнении двух указателей?

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,

Однако вы не можете сравнивать указатели с реляционными операторами (<, >, <=, >=), которые не указывают на элементы одного и того же массива или после конца одного и того же массива.

Другие вопросы по тегам