2010-07-31 3 views

ответ

2

Вы можете добиться того, что вы хотите таким образом:

void foo(int *array) { } 

int column_size = 5; 

int main() { 
    int array[column_size][2]; 

    foo(&array[0][0]); 

    return 0; 
} 

хотя вы должны позаботиться о том, как вы читаете элементы внутри функции foo. Для того, чтобы прочитать array[c][r] элемент, который вы должны сделать:

int element = *(array + c * column_size + r); 

Общая функция прибудете элемент:

int get_element(int *array, int row, int column, int column_size) { 
    int element = *(array + row * column_size + column); 
    return element; 
} 

Итак, если вы, скажем, в 2D массив как INT array[M][N] и вы хотите получить элемент array[i][j], который вы просто вызываете функцию следующим образом:

getElement(&array[0][0], i, j, N) 

Почему это работает?

Причина, по которой вышеуказанная функция работает, может быть выяснена, если вы знаете, как массивы 2D сохраняются в памяти. Массивы сохраняются строка за строкой, так скажем, у вас есть следующий массив:

int a[3][3] = {{1, 2, 4}, {5, 6, 7}, {8, 9, 10}}; 

давайте предположим, что целое 4 байта и & а [0] [0] соответствует 0x10 адресу памяти. Затем 1 сохраняется в 0x10 адрес памяти, 2 сохраняется в 0x14, ..., 7 сохраняется в 0x24 адрес памяти, ... и 10 сохраняется в адресе памяти 0x30 (см. Следующую таблицу).

*Memory* 

Memory address => Value => Pointer pointing at this memory address 

    0x10  => 1 => &a[0][0] 
    0x14  => 2 => (&a[0][0] + 1) or (&a[0][1]) 
    0x18  => 4 => (&a[0][0] + 2) or (&a[0][2]) 
    0x1c  => 5 => (&a[0][0] + 3 * 1 + 0) or (&a[1][0]) 
    0x20  => 6 => (&a[0][0] + 3 * 1 + 1) or (&a[1][1]) 
    0x24  => 7 => (&a[0][0] + 3 * 1 + 1) or (&a[1][2]) 
    0x28  => 8 => (&a[0][0] + 3 * 2 + 0) or (&a[2][0]) 
    0x2c  => 9 => (&a[0][0] + 3 * 2 + 1) or (&a[2][1]) 
    0x30  => 10 => (&a[0][0] + 3 * 2 + 2) or (&a[2][2]) 

Теперь, когда у вас есть следующий указатель:

int *pt = (&a[0][0] + 2); 

pt указатель будет указывать 2 элемента после a[0][0]. Таким образом, pt указывает на [0] [2]. *pt будет равна 4.

Теперь предположим, что вы хотите получить элемент a[i][j]. Чтобы получить этот элемент , вам нужно переместить i * COLUMN_SIZE элементов, чтобы попасть в правильную строку, где находится элемент (каждая строка содержит COLUMN_SIZE элементов), а затем вам нужно добавить j, чтобы попасть в нужный столбец.

Если вы хотите получить a[2][1] (где COLUMN_SIZE = 3), то 2 * COLUMN_SIZE = 6 + 1 = 7. Итак, чтобы получить элемент a[2][1], вы делаете *(&a[0][0] + 2 * 3 + 1) или *(&a[0][0] + 7).

Для некоторых замечательных уроков по указателям, посмотрите здесь: Stanford CS Ed Library.

+0

Но функция может ссылаться только на массив как 1D-массив (вектор), а не как 2D-массив с правильным размером. –

+0

@ jonathan-leffler Да, я знал о коде, который вы публикуете. Но реальный вопрос касался пропущенных указателей, поэтому @functional сделал то, что я хотел. Благодарю. – Ockonal

+0

@функциональный Отличный ответ! – Ockonal

2

Это более или менее то же самое - за исключением бит, которые отличаются друг от друга, конечно.

#include <stdio.h> 

enum { DIM = 6 }; 

static void Bar(int arr[][DIM], int n) 
{ 
    int i, j; 
    for (i = 0; i < n; i++) 
    { 
     for (j = 0; j < DIM; j++) 
      printf(" %2d", arr[i][j]); 
     putchar('\n'); 
    } 
} 

int anotherArr[][DIM] = 
{ 
    { 1, 2, 3, 4, 5, 6 }, 
    { 6, 5, 4, 3, 2, 1 }, 
    { 0, 0, 0, 0, 0, 0 }, 
    { -1, -2, -3, -4, -5, -6 }, 
}; 

int main(void) 
{ 
    Bar(anotherArr, 4); 
    return(0); 
} 
+0

Хм, почему вы используете перечисление для хранения размера массива? – Ockonal

+0

Можете ли вы сделать то же самое, но объявите параметр для Bar как указатель вместо массива? – sholsapp

+0

@Ockonal: потому что я говорю C лучше, чем C++. –

0
void Foo(int **arr) { } 
int someArr[10][10]; 
Foo(someArr); 
+1

Это будет круто, потому что он ожидает массив указателей, а 2D-массив не совпадает с массивом указателей. –

+0

'someArr' не типа' (int **) ', а типа' (int (*) [10]) ' – 2010-07-31 23:50:56

Смежные вопросы