Арифметика указателя C - PullRequest
       9

Арифметика указателя C

13 голосов
/ 22 января 2010

Учитывая этот код:

int *p, *q;

p = (int *) 1000;
q = (int *) 2000;

Что такое q - p и как?

Ответы [ 5 ]

32 голосов
/ 22 января 2010

Это на самом деле не определено, согласно стандарту. Арифметика с указателями не гарантируется, если только указатели не указывают ни на элемент в одном массиве, ни сразу за ним.

Соответствующим разделом стандарта является 6.5.6: 9 (черновик n1362 c1x, но он не изменился с c99), в котором говорится:

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

Скорее всего, вы получите 250, если ваш int тип данных составляет 4 байта, но нет гарантии. Неопределенное поведение (в отличие от поведения, определенного реализацией) означает только это, неопределенное. Может произойти все, вплоть до полного уничтожения значительной части пространства-времени.

Курс повышения квалификации:

  • Определенное поведение - это то, что предписано стандартом. Реализации должны сделать это, чтобы соответствовать.
  • Определенное реализацией поведение оставлено на усмотрение реализации, но оно должно четко документировать это поведение. Используйте это, если вас не слишком заботит переносимость.
  • Неопределенное поведение означает, что все может случиться. Никогда не делай этого!
8 голосов
/ 22 января 2010

q - p равно 250.

2000 - 1000 = 1000
1000 / sizeof(int) = 250

арифметика указателя, предполагая, что sizeof (int) равен 4. <Ч /> Редактировать: ОК, чтобы уточнить. В C, когда два указателя имеют один и тот же тип, тогда разница между ними определяется количеством вещей указательного типа между ними. Например,

struct foo { int ar[1000]; } big[10];
char small[10];

struct foo *fs, *fe;
char *ss, *se;

fs = &big[0]; fe = &big[9];
ss = &small[0]; se = &small[9];

fe - fs == se - ss;

То есть разница между двумя указателями в этом случае заключается в количестве элементов массива между ними. В данном случае это 0, 1, ... 8 или 9 элементов.

2 голосов
/ 22 января 2010

Ответ : q-p будет 250, если вы находитесь на машине, где int равно 4 байта.

Расчет составляет:

q - p = 1000 1000/4 (размер целого) = 250

Идея, стоящая за этим :

Идея арифметики указателей заключается в том, что если у вас есть int указатель на 1000 и int указатель на 2000, и вы спрашиваете разницу, вы не спрашиваете, что такое 2000- 1000. То, что вы спрашиваете, , сколько int я могу разместить между ними.

Это очень удобно для всех видов операций, например:

int *i = 100;
i++; // This is **not** 101, it is 104, cause you actually want the next place an int could fit in memory.

Это особенно удобно при работе с массивами. Массив целых чисел (определенный int arr[10]) в основном обрабатывается как указатель. Когда вы пишете arr[5], компилятор преобразует его в *(arr + 5), то есть добавляет 5 к указателю int с именем arr и получает значение по этому адресу.

Причина, по которой это работает, заключается в том, что arr + 5 делает не означает «добавьте 5 к значению arr», это означает «добавьте все, что необходимо к значению arr для продвижения вперед 5 * 1036» * s ", или, точнее," добавьте 5 * sizeof(int) к значению arr "

2 голосов
/ 22 января 2010

q-p должно возвращать, сколько шагов с приращением вы должны сделать, чтобы перейти от p к q. Который равен 1000 / sizeof(int) и равен 250. Помните, что q++ фактически перейдет к следующему элементу типа int, а не к его середине, поэтому следует добавить 4 к фактическому значению указателя. Отсюда и результат.

0 голосов
/ 22 января 2010

Поскольку p указывает на int и q, q-p будет 1000.

...