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

127
02 июля 2019, 08:20

Необходимо определить размер массива, переданного в функцию. Пробовал вот так:

void foo(int* Array)
{
    const unsigned int SIZE = sizeof(Array)/sizeof(int);
}

но в SIZE сохраняется 1, независимо от размера массива. Можно, конечно, вместе с массивом передать в функцию и его размер, но может существует более изящное решение?

P.S.: Кстати, заметил нечто странное. Запускал эту программу через Visual Studio и Qt. В VS в SIZE сохраняется 1, а в Qt 2.

Answer 1

У вас параметр функции 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 <size_t N>
void foo( int ( &Array )[N] )
{
    const size_t n = N;
}

В этом случае компилятор, используя шаблон, создаст столько функций, сколько массивов разной длины были использованы в качестве аргумента.

READ ALSO
Интегральные типы

Интегральные типы

Почему конструкция switch case работает только с интегральными типами, и что вообще такое интегральные типы?

129
Отправка рабочего стола через TCP (boost + opencv)

Отправка рабочего стола через TCP (boost + opencv)

Всех приветствуюНаткнулся на пример отправки изображения камеры с клиента на сервер, решил попробовать отослать изображение рабочего стола...

160
Метод прогонки/Алгоритм Томаса(С++) [закрыт]

Метод прогонки/Алгоритм Томаса(С++) [закрыт]

Здраствуйте! Хотел бы попросить Вас о маленькой помощиПроблема заключается в следующем : должен найти решения матрицы методом прогонки и в конечном...

134
как убрать кавычки

как убрать кавычки

Допустим нужно ввести строку Например : ((1&1)^(0|1)) Чтобы он вывел : 0 нужно превратить это "((1&1)^(0|1))" в это ((1&1)^(0|1))

132