Форум » C/C++ для начинающих (C/C++ for beginners) » Передача указателя на массив, тип которого определен с помощью typedef. » Ответить

Передача указателя на массив, тип которого определен с помощью typedef.

Сыроежка: Эта тема создана мною благодаря вопросу на Stackoverflow Passing a pointer to a typedef'ed array. То есть когда тип массив определен с помощью typedef, то у начинающих программистов вызывает трудности, как правильно объявить соответствующий параметр функции, принимающий массив. В исходном вопросе тип массива определяется следующим образом [pre2] typedef unsigned char multi_array[4][4];[/pre2] И автор вопроса хочет передать этот массив в функцию, которая выводит на консоль элементы массива. Он объявляет функцию следующим образом [pre2] void print_array(multi_array* arr);[/pre2] Фактически, параметр функции имеет тип unsigned char ( * )[4][4]. Так можно передавать массив в функцию, хотя это и не общепринятый способ. Преимущество передачи массива в функцию через указатель на весь массив состоит в том, что в функции можно вычислить размерности элементов массива, не передавая их явно как дополнительные аргументы функции. Ниже показана демонстрационная программа. [pre2] #include <stdio.h> enum { N = 4 }; typedef unsigned char multi_array[N][N]; void print_array( multi_array *arr ) { for ( size_t i = 0; i < sizeof( *arr ) / sizeof( **arr ); i++ ) { for ( size_t j = 0; j < sizeof( **arr ) / sizeof( ***arr ); j++ ) { printf("%2d ", ( *arr )[ i ][ j ]); } printf("\n"); } } int main( void ) { multi_array arr; for ( size_t i = 0; i < N; i++ ) { for ( size_t j = 0; j < N; j++ ) { arr[ i ][ j ] = N * i + j; } } print_array( &arr ); } [/pre2] Вывод программы на консоль: [pre2] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [/pre2] Как видно из программы разыменовывая (и дважды разыменовывая) указатель, объявленный в качестве параметра, мы получаем lvalue на исходный массив. Это позволяет вычислить размерности массива с помощью выражении sizeof( *arr ) / sizeof( **arr ) и sizeof( **arr ) / sizeof( ***arr ). Для обращения к конкретному элементу типа unsigned char массива нужно использовать выражение ( *arr )[ i ][ j ], так как операция разыменования имеет более низкий приоритет, чем операция индексации. А нам сначала нужно получить сам массив, на который ссылается указатель, и лишь затем применять операцию индексирования. Однако более общепринятый способ передачи массивов в функции состоит в том, чтобы соответствующий параметр функции объявить как указатель на первый элемент массива. Для заданного в исходном вопросе массива соответствующий параметр будет выглядеть как char ( *arr )[4]. Этот же параметр можно также записать как исходное объявление массива, то есть в виде multi_array arr. Компилятор сам приведет это объявление массива к объявлению указателя на его первый элемент. В этом случае требуется также передавать размерность "внешнего" под-массива, так как внутри функции вычислить его невозможно, так как мы имеем дело с указателем на первый элемент массива. То есть выражение sizeof( arr ) вернет размерность указателя, а не размер памяти, занимаемый всем массивом. Ниже приведена соответствующая демонстрационная программа. [pre2] #include <stdio.h> enum { N = 4 }; typedef unsigned char multi_array[N][N]; void print_array( multi_array arr, size_t n ) { for ( size_t i = 0; i < n; i++ ) { for ( size_t j = 0; j < sizeof( *arr ) / sizeof( **arr ); j++ ) { printf("%2d ", arr[ i ][ j ]); } printf("\n"); } } int main( void ) { multi_array arr; for ( size_t i = 0; i < N; i++ ) { for ( size_t j = 0; j < N; j++ ) { arr[ i ][ j ] = N * i + j; } } print_array( arr, N ); } [/pre2] Обратите внимание, что согласно стандарту языка Cфункция main без параметров должна быть объявлена как [pre2] int main( void )[/pre2] Так же не следует использовать магические числа вроде числа 4, используемого в программе исходного вопроса. Используйте именованные константы.

Ответов - 0



полная версия страницы