== для сравнения указателей - PullRequest
28 голосов
/ 03 апреля 2012

Я цитирую «Язык программирования C» Кернигана и Ричи:

Любой указатель может быть осмысленно сопоставлен на равенство или неравенство с нулем.Но поведение не определено для арифметики или сравнения с указателями, которые не указывают на элементы одного и того же массива.(Существует одно исключение: адрес первого элемента после конца массива может использоваться в арифметике указателей.)

Означает ли это, что я не могу полагаться на == для проверки равенства различныхуказатели?В каких ситуациях это сравнение приводит к неверному результату?

Ответы [ 5 ]

33 голосов
/ 03 апреля 2012

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

8 голосов
/ 03 апреля 2012

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

Я думаю, что ваша ошибка - считать K & R нормативным.См. Стандарт C99 (хорошая HTML-версия здесь: http://port70.net/~nsz/c/c99/n1256.html), 6.5.9 об операторе равенства. Вопрос о неопределенности сравнений относится только к реляционным операторам (см. 6.5.8):

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

2 голосов
/ 03 апреля 2012

Я интерпретирую это следующим образом:

short a[9];
int b[12];
short * c = a + 9;

Здесь можно сказать, что

c > a

потому что c получается из a через арифметику указателей,

но не обязательно, что

b == c

или

c <= b

или что-то похожее, потому что они являются результатом разных массивов, чей порядок и выравнивание в памяти не определены.

0 голосов
/ 03 мая 2013

Вы можете сделать == и != с указателями из разных массивов.

<, <=,>,> = не определено.

0 голосов
/ 03 апреля 2012

Вы не можете использовать сравнение указателей для сравнения указателей, которые указывают на разные массивы.

Итак:

int arr[5] = {1, 2, 3, 4, 5};

int * p = &arr[0];

int anotherarr[] = {1, 2};

int * pf = &anotherarr[0];

Вы не можете сделать if (p == pf), поскольку p и pf не указывают на один и тот же массив. Это приведет к неопределенному поведению.

Вы можете положиться на сравнение указателей, если они указывают в одном массиве.

Не уверен насчет арифметического случая сам.

...