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

== для сравнения указателей

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

Ответ 3

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

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

Здесь справедливо сказать, что

c > a

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

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

b == c

или

c <= b

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

Ответ 4

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

Итак:

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 не указывают на тот же массив. Это приведет к поведению undefined.

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

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

Ответ 5

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

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