C-указатель арифметики
С учетом этого кода:
int *p, *q;
p = (int *) 1000;
q = (int *) 2000;
Что такое q - p
и как?
Ответы
Ответ 1
На самом деле undefined, в соответствии со стандартом. Арифметика указателя не гарантируется работать, если указатели не указывают либо на элемент в, либо за пределы того же массива.
Соответствующий раздел стандарта - 6.5.6: 9 (n1362 черновик c1x, но это не изменилось с c99), который гласит:
Когда два указателя вычитаются, оба указывают на элементы одного и того же объекта массива, или один за последним элементом объекта массива; в результате возникает разница индексы двух элементов массива.
Скорее всего, вы получите 250, если ваш тип данных int
- 4 байта, но нет гарантии. Поведение Undefined (в отличие от поведения, определенного реализацией) означает только undefined. Все может произойти, вплоть до полного уничтожения значительной части пространства-времени.
Курс переподготовки:
- Определенное поведение - это то, что предусмотрено стандартом. Реализации должны делать это, чтобы быть совместимыми.
- Поведение, определяемое реализацией, остается до реализации, но оно должно четко документировать это поведение. Используйте это, если вы не слишком заботитесь о переносимости.
- Undefined поведение означает, что все может случиться. Никогда не делай этого!
Ответ 2
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 элементов.
Ответ 3
q-p
должен возвращать количество шагов с шагом, которое вы должны сделать, чтобы перейти от p
в q
. Это 1000 / sizeof(int)
и равно 250. Помните, что q++
действительно перейдет к следующему элементу типа int, а не к середине его, поэтому он должен добавить 4 к фактическому значению указателя. Следовательно, результат.
Ответ 4
Ответ:
q-p будет 250, если вы на машине, где int
- 4 байта.
Вычисление:
q - p = 1000
1000/4 (размер int) = 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.
Это особенно полезно при работе с массивами. Массив ints (определенный int arr[10]
) в основном обрабатывается как указатель. Когда вы пишете arr[5]
, компилятор переводит его на *(arr + 5)
, т.е. Добавляет 5 к указателю int
, называемому arr
, и получает значение по этому адресу.
Причина, по которой это работает, заключается в том, что arr + 5
означает не означает "добавить 5 к значению arr", это означает "добавить все, что является neceassary, к значению arr для перехода вперед 5 int
s" или, точнее, "добавить 5 * sizeof(int)
к значению arr"
Ответ 5
Поскольку p указывает на int и, следовательно, q, q-p будет 1000.