Страницы

Поиск по вопросам

вторник, 18 декабря 2018 г.

Как узнать размер массива переданного в функцию? [дубликат]

На данный вопрос уже ответили: Передача статического одномерного массива определённого размера в функцию 6 ответов Необходимо определить размер массива, переданного в функцию. Пробовал вот так:
void foo(int* Array) { const unsigned int SIZE = sizeof(Array)/sizeof(int); }
но в SIZE сохраняется 1, независимо от размера массива. Можно, конечно, вместе с массивом передать в функцию и его размер, но может существует более изящное решение?
P.S.: Кстати, заметил нечто странное. Запускал эту программу через Visual Studio и Qt. В VS в SIZE сохраняется 1, а в Qt 2.


Ответ

У вас параметр функции foo объявлен как указатель типа int *
void foo(int* Array); ^^^^^^^^^^
Следовательно внутри функции выражение
sizeof(Array)/sizeof(int)
эквивалентно выражению
sizeof(int *)/sizeof(int)
Если, например, размер указателя, то есть типа int *, равен 8 байтам, а размер типа int равен 4 байтам, то в итоге вы получите 2. Если же при этом размер типа int равен также 8 байтам (64-битовая ОС), то вы получите в итоге 1.
Но даже если вы объявите эту функцию как
void foo(int Array[]);
или даже так
void foo(int Array[10]);
все равно параметр функции неявно преобразуется в указатель на элемент массива. То есть эти два объявления функции объявляют одну и ту же функцию и эквивалетны следующему объявлению
void foo(int* Array);
Так что внутри функции вы снова будете иметь дело с указателем.
Когда массив передается по значению, то вам следует также объявлять второй параметр, который задает размер массива.
Или массив должен иметь некоторый граничный элемент с уникальным значением, по которому можно определить число актуальных элементов, как это имеет место, например, со строками, когда строки завершаются нулем, то есть символом '\0'
То есть в общем случае вам следует объявлять функцию как
void foo(int* Array, size_t n);
где n - это размер массива.
Другой подход - это объявлять параметр как ссылку на массив. В этом случае длина массива будет известна внутри функции. Например
void foo( int ( &Array )[10] ) { const size_t = sizeof( Array)/ sizeof( *Array ); }
Недостаток этого объявления состоит в том, что эта функция может иметь дело только с массивами, заданного в ее параметре размера.
Чтобы обойти это ограничение, вы можете объявить шаблонную функцию. Например,
template void foo( int ( &Array )[N] ) { const size_t = N; }
В этом случае компилятор, используя шаблон, создаст столько функций, сколько массивов разной длины были использованы в качестве аргумента.

Комментариев нет:

Отправить комментарий