On-line: гостей 0. Всего: 0 [подробнее..]
Программисты всех стран, объединяйтесь!

АвторСообщение



ссылка на сообщение  Отправлено: 20.09.18 15:07. Заголовок: Передача указателя на массив, тип которого определен с помощью typedef.


Эта тема создана мною благодаря вопросу на Stackoverflow Passing a pointer to a typedef'ed array.

То есть когда тип массив определен с помощью typedef, то у начинающих программистов вызывает трудности, как правильно объявить соответствующий параметр функции, принимающий массив.

В исходном вопросе тип массива определяется следующим образом

 
typedef unsigned char multi_array[4][4];


И автор вопроса хочет передать этот массив в функцию, которая выводит на консоль элементы массива.

Он объявляет функцию следующим образом

 
void print_array(multi_array* arr);


Фактически, параметр функции имеет тип unsigned char ( * )[4][4].

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

Ниже показана демонстрационная программа.

 
#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 );
}


Вывод программы на консоль:

 
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15


Как видно из программы разыменовывая (и дважды разыменовывая) указатель, объявленный в качестве параметра, мы получаем lvalue на исходный массив. Это позволяет вычислить размерности массива с помощью выражении sizeof( *arr ) / sizeof( **arr ) и sizeof( **arr ) / sizeof( ***arr ).

Для обращения к конкретному элементу типа unsigned char массива нужно использовать выражение ( *arr )[ i ][ j ], так как операция разыменования имеет более низкий приоритет, чем операция индексации. А нам сначала нужно получить сам массив, на который ссылается указатель, и лишь затем применять операцию индексирования.

Однако более общепринятый способ передачи массивов в функции состоит в том, чтобы соответствующий параметр функции объявить как указатель на первый элемент массива. Для заданного в исходном вопросе массива соответствующий параметр будет выглядеть как char ( *arr )[4].

Этот же параметр можно также записать как исходное объявление массива, то есть в виде multi_array arr. Компилятор сам приведет это объявление массива к объявлению указателя на его первый элемент.

В этом случае требуется также передавать размерность "внешнего" под-массива, так как внутри функции вычислить его невозможно, так как мы имеем дело с указателем на первый элемент массива. То есть выражение sizeof( arr ) вернет размерность указателя, а не размер памяти, занимаемый всем массивом.

Ниже приведена соответствующая демонстрационная программа.

 
#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 );
}


Обратите внимание, что согласно стандарту языка Cфункция main без параметров должна быть объявлена как
 
int main( void )


Так же не следует использовать магические числа вроде числа 4, используемого в программе исходного вопроса. Используйте именованные константы.

Спасибо: 0 
ПрофильЦитата Ответить
Новых ответов нет


Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 10
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет