Является ли вычитание указателей, не указывающих на разные элементы одного и того же массива, допустимым в C? - PullRequest
3 голосов
/ 12 марта 2012

Является ли вычитание указателей, не указывающих на разные элементы одного и того же массива, допустимым в C?

Гарантируется ли что-либо, как указано ниже, в соответствии со стандартами C? Я смутно помню, что читал, что это не верно?

int * a;
int * b;
a = (int*) 100;
b = (int*) 200;
printf("%d\n", b-a);

Это даст мне 25.

Ответы [ 4 ]

6 голосов
/ 12 марта 2012

Из спецификации C, Приложение J.2 Неопределенное поведение :

Вычитаются указатели, которые не указывают или не выходят за один и тот же объект массива (6.5.6).

6.5.6 Аддитивные операторы , пункт 9 гласит:

Когда вычтены два указателя, оба должны указывать на элементытот же самый объект массива, или один после последнего элемента объекта массива;В результате получается разница индексов двух элементов массива.

Вот оно, ваш пример вызывает неопределенное поведение.Тем не менее, на большинстве систем это будет работать просто отлично.Возможно, вы do хотите изменить формат printf на %td, чтобы указать, что вы печатаете тип ptrdiff_t.

4 голосов
/ 12 марта 2012

Это неопределенное поведение.

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

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

Конечно, он, скорее всего, будет работать на большинстве компиляторов, и вы получите 25, потому что sizeof(int) == 4 на вашей платформе.Если бы они были char *, вы бы получили 100. (возможно, или это может привести к сбою, в этом вся прелесть UB).

0 голосов
/ 12 марта 2012

Конечно, это не определено.Вычитание двух произвольных указателей (рассматриваемых как целые числа) даже не гарантирует кратность размера вашего объекта.

0 голосов
/ 12 марта 2012

Даже стандарт не обещает определенного поведения, результат правильный.Целое число нуждается в вашей архитектуре 4 байта.Таким образом, разница дает вам число значений integer , в которых оба указателя находятся отдельно.Вы можете использовать разницу в качестве индекса или смещения в массиве.По той же причине

  int *p = (int*) 100;
  p++;

приведет к р = 104.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...