2016-01-06 3 views
1

У меня есть код, как это:Matrix, указатели, C *

void print_matrix(int **a, int n) { 
    int i, j; 
    for(i = 0; i < n; i++) { 
     for(j = 0; j < n; j++) 
      printf("%d\t", *(a+i*n+j)); 
     putchar('\n'); 
    } 
} 

int main() { 
    int matrix[3][3]; 

    insert (matrix); /* Function that reads Matrix from stdin */ 
    print_matrix(matrix, 3); 
    return 1; 
} 

Я получаю ошибку GCC:

expected ‘int **’ but argument is of type ‘int (*)[3]

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

Указатели не являются массивами, я это понимаю. Я где-то читал, что элементы не являются последовательными, в этом случае это может произойти: 111 222 333 -> 111 - адрес первого массива int, 222 - адрес второго массива int, а 333 - адрес третьего массива int. Но если это так, я не понимаю, почему GCC дает мне ошибку.

Прежде всего, я хотел бы, чтобы кто-то подтвердил, что то, что я прочитал, верно. Тогда я был бы очень признателен, если бы кто-нибудь мог дать мне ответ.

Обратите внимание, что я понимаю, что *(a+i*n+j) неверно, если память для матрицы не является последовательной.

С уважением.

+2

типы не эквивалентны, 'INT [3] [3]' является contigous хранение 9 целых чисел, в то время как '' INT ** является указателем (* возможно, массив указателей *) указателей. –

+0

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

+1

Но вы ошибаетесь, можете ли вы написать 'a [j] [i]'? –

ответ

4

Когда вы передаете int[3][3], функция получает указатель на (int*)[3], который a указатель на массив из 3 int's. rray преобразуется в указатель на свой первый элемент, когда вы передаете его функции.

Соответственно отрегулируйте функцию. Один из способов - получить его как указатель на массив. Индексирование массива также неверно. Вы можете индексировать точно так же, как вы бы указали реальный массив.

void print_matrix(int (*a)[3], int n) { 

    int i, j; 
    for(i = 0; i < n; i++) { 
     for(j = 0; j < n; j++) 
      printf("%d\t", a[i][j]); 
     putchar('\n'); 
    } 

} 

Если вы используете C99, вы можете пройти оба измерения:

void print_matrix(int x, int y, int a[x][y]) { 

    int i, j; 
    for(i = 0; i < x; i++) { 
     for(j = 0; j < y; j++) 
      printf("%d\t", a[i][j]); 
     putchar('\n'); 
    } 

} 

и называют его как:

print_matrix(3, 3, matrix); 

Просто, чтобы показать, как вы бы получить доступ к человеку " массивы ":

void print_matrix(int (*a)[3], int n) { 
    int i, j; 
    for(i = 0; i < n; i++) { 
     int *p = a+i; 
     for(j = 0; j < 3; j++) 
      printf("%d\t", p[j]); 
     putchar('\n'); 
    } 

} 
+0

Когда вы передаете int [3] [3], функция получает указатель на (int *) [3], который является указателем на массив из 3 int. Поскольку массив передается в указатель на его первый элемент, когда вы передаете его функции. - Не могли бы вы объяснить это немного больше? –

+0

В C вы не можете ни передавать, ни возвращать * массив * в/из функции. Он всегда преобразуется в указатель на его первый элемент. Таким образом, массив теряет информацию о размере и становится просто указателем (внутри функции), что также является причиной того, что вы не можете использовать 'sizeof' на нем, чтобы получить его фактический размер. См. [Что такое разложение массива?] (Http://stackoverflow.com/questions/1461432/what-is-array-decaying), который специально охватывает эту тему. –

+0

Итак, в основном, когда я перехожу к функции int [3] [3] ТОЛЬКО первый int [3] преобразуется в указатель, а затем я получаю (int *) [3] и это указатель на массив из 3 целых чисел, а не 3 указателя на 3 разных массива? –

0

int** является Указатель на указатель (указывая на int).

int[3][3], в качестве аргумента функции, преобразуется в указатель на массив int - см Is an array name a pointer?

Так типы не совпадают, так как компилятор говорит вам. .

Примечание: если вы делаете арифметику указателей в функции, вы можете передать int *a вместо int **a (литья: print_matrix((int *)matrix, 3); Это некрасиво, но и помогает понять, что происходит, а именно - int[3][3] массива хранится в памяти точно как int[9] массив, и если вы вычисления int позиции себя, как вы делаете, это будет также работать как 1D массив.

+0

Почему нисходящий ...? – Ilya

+0

'int [3] [3]' - массив массивов. Нет «как указатель», потому что это не одно. Это может быть вопросом терминологии, но я думаю, что это важно, потому что это смущает так много новичков (и некоторых не новичков) – juanchopanza

+0

В качестве параметра int [3] [3] действительно преобразован в указатель. Но вы правы, я обновляю описание, это не совсем понятно. Как бы то ни было, я смешиваю фактическое содержимое переменных параметров с типами, которые компилятор «видит». – Ilya

1

Если вы хотите, чтобы n менялся (и был квадратным), лучше всего выделить и использовать один размерный массив и умножить, когда вам нужна другая строка.

int matrix[3*3]; 

Как его использовать?

matrix[row*3+col] = 5; 

Как это передать.

f(int *a,int n) 
Смежные вопросы