Четвертый способ - передать типизированный указатель на весь массив, как я упоминал в комментарии.Я не тестировал код, но вы поймете идею.Обратите внимание, что *two_dim_ptr
- это весь 2D-массив, а sizeof(*two_dim_ptr)
- это число всех элементов, умноженное на int
(это один из немногих случаев, когда выражение массива не уменьшаетсяна указатель).
**two_dim_ptr
- это первый элемент двумерного массива, одномерный массив с NUM_TWO_DIM_COLS
элементами.Следовательно, sizeof(*two_dim_ptr)/sizeof(**two_dim_ptr)
вычисляет количество строк.
***two_dim_ptr
- первый элемент первой строки, здесь int
;Следовательно, sizeof(**two_dim_ptr)/sizeof(***two_dim_ptr)
вычисляет количество элементов в строке.
Вычисление границ индекса с использованием размера элементов имеет преимущество в обслуживании, которое не нужно изменять коду, если вы измените тип элемента илипостоянные имена.Недостатком является то, что его сложнее читать.
void iterate_two_dim_p(int (*two_dim_ptr)[NUM_TWO_DIM_ROWS][NUM_TWO_DIM_COLS]) { //function parameter is pointer to array of specific size
printf("True pointer to two dim array passed\n" );
for(int row = 0; row < sizeof(*two_dim_ptr)/sizeof(**two_dim_ptr); row++) {
for(int col = 0; col < sizeof(**two_dim_ptr)/sizeof(***two_dim_ptr); col++) {
printf("two_dim_ptr[%d][%d] = %-4d ", row,col, two_dim_ptr[row][col] );
}
printf("\n");
}
printf("\n");
}
Вы бы назвали его с помощью iterate_two_dim_p(&two_dim);
, то есть вы берете адрес всего массива. (ПозицияАргументом для оператора адреса является еще один случай, когда массивы не распадаются. Результатом является правильно введенный адрес двумерного массива, а не только адрес его первой строки. Конечно, все адреса численно идентичны, потому что адрес составногоtype - это адрес его первого элемента, правила, которое применяется рекурсивно, так что (size_t)&two_dim == (size_t)two_dim && (size_t)two_dim == (size_t)*two_dim
. Разница в типах.)