Вопрос по указателю в C? - PullRequest
2 голосов
/ 15 июня 2009
int a[A][B];
int* p = a[i];  //i<A-1

тогда какова действительная фраза предложения ниже?

p++;
p+=B;

Ответы [ 8 ]

13 голосов
/ 15 июня 2009

p++ -> Перейти к следующему столбцу в матрице

p+=B -> Перейти к следующей строке (в том же столбце) в матрице.

4 голосов
/ 15 июня 2009

Для многомерных массивов нужно помнить, что размеры применяются слева направо, что упрощает визуализацию. например:

int p[A][B][C];

Это будет построено как:

[][]--[][][][]--[][]_ _ _[][]--[][]   [][]--[][][][]--[][]_ _ _[][]--[][]
|---A----||---A----|     |---A----|---|---A----||---A----|     |---A----|
|---------------A*B---------------|   |---------------A*B---------------|
|---------------------------------A*B*C---------------------------------|

так что если у вас есть p [i] [j] [k], то на самом деле (p + i + Bj + BCk)

0 голосов
/ 16 июня 2009

Это своего рода мета-ответ, нацеленный как на Юстикулу, так и на оригинальный постер.

Массивы вырождаются в указатели, но это не одно и то же. Просто потому, что синтаксис для получения [3] [7] [1] одинаков, если a является указателем на указатель на указатель на int по сравнению с массивом-массивом-массивом-массивом -int не означает, что фактическая операция одинакова.

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

a[i] == *(a+i) == i[a]

независимо от типа массива a.

Все ответы на вопросы в этой теме могут быть получены из этого.

int a[3][2][17];      //a is an array of length 17.
int (*b)[3][2] = a[5]; //b is a pointer to the fifth element of a
int (*c)[3] = b[1];    //c points to the first element of b.
b += 1; // b now points to the sixth element of a. (c is unchanged)
c += sizeof(*b); // c points to the first element of b again.

Обратите внимание, что ничего из этого не сработало бы, если бы a не было смежным. Если это не сработает, то массивы массивов будут работать иначе, чем массивы чего-либо еще.

0 голосов
/ 16 июня 2009

Просто для продолжения разговора (хотя я не могу ответить на пост cbailey напрямую без достаточного количества повторений ...)

Существует большая разница между объявлением многомерного массива в стеке и в куче.

Поскольку abelenky может достигнуть этого, объявление многомерного массива в стеке всегда приведет к непрерывной памяти. Я полагаю, что стандарт C на самом деле где-то утверждает это, но даже если этого не произойдет, каждый компилятор на планете будет гарантировать его непрерывность. Это означает, что в конце дня вы также можете использовать массив с одним измерением, потому что компилятор в любом случае преобразуется в него.

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

0 голосов
/ 16 июня 2009

Чтобы ответить на этот вопрос, вам сначала нужно понять, как многомерные массивы хранятся в памяти в C.

int a[A][B];

Не принимая во внимание оптимизацию того, как он находится в памяти, первый индекс (A) фактически будет массивом указателей на второй индекс (B). Хотя память может быть смежной, нет гарантии .

Таким образом:

int a[A][B];
int **b;

Разница между a и b выше заключается в том, что память для a выделяется, когда она входит в область действия.

Имея это в виду, чтобы ответить на ваш вопрос:

int* p = a[i]; // p = a[i][0]
p++; // p = a[i][1]
p+=B; // p = a[i][1+B]

С современным компилятором, вероятно, был выделен один непрерывный блок памяти, что дает вам эквивалент:

p = a[i+1][1];

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

0 голосов
/ 15 июня 2009
p = a[A-1]

совпадает с

p = &a[A-1][0]

так

p++

результаты в

p == &a[A-1][1]

и затем делает

p+=B

приведет к

p == &a[A-1][1+B] == &a[A][1] // outside allocated memory
0 голосов
/ 15 июня 2009

После инициализации у a есть память для A B, а p указывает на B i'th (на основе 0). Более поздние операции указывают на B * (i + 1) + 1 '.

0 голосов
/ 15 июня 2009

Ответ довольно прост, если вы рисуете матрицу a [A] [B] в форме памяти, то есть вектор и начинаете с p, указывающего на начало [i], а затем применяете эти операции.

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