Найдите размер массива в C, используя оператор sizeof и арифметику указателя
В этом посте представлен обзор некоторых доступных альтернатив для определения размера массива в C.
1. оператор sizeof
Стандартным способом является использование sizeof оператор, чтобы найти размер массива в стиле C. sizeof Оператор над массивом возвращает общую память, занимаемую массивом, в байтах. Чтобы определить общее количество элементов массива, трюк состоит в том, чтобы разделить общую память, занимаемую массивом, на размер каждого элемента. Это показано ниже на языке C:
int main ( void )
size _ т n = sizeof ( arr ) / sizeof ( arr [ 0 ] ) ;
printf ( «The size of the array is %d» , n ) ;
Для простоты и улучшения читаемости кода предлагается сконструировать из него МАКРОС, как показано ниже:
#define SIZEOF(a) sizeof(a)/sizeof(*a)
int main ( void )
size _ т n = SIZEOF ( arr ) ;
printf ( «The size of the array is %d» , n ) ;
Мы знаем, что массив распадается на указатель при передаче функции в качестве аргумента независимо от того, объявлен ли параметр как int[] или нет. Таким образом, описанный выше подход работает только со статическими массивами, но не работает с динамически выделенными массивами и параметрами функций, поскольку они оба включают указатели.
#define N 5
// массив распадается на указатель
size_t getSize ( int * arr )
size _ т n = sizeof ( arr ) / sizeof ( arr [ 0 ] ) ;
int main ( void )
int * a = malloc ( N * sizeof ( int ) ) ;
printf ( «%zu\n» , sizeof ( a ) / sizeof ( a [ 0 ] ) ) ; // это не сработает
printf ( «%zu\n» , getSize ( b ) ) ; // это не сработает
2. Использование арифметики указателей
Хитрость заключается в использовании выражения (&arr)[1] — arr чтобы получить массив arr размер. Оба arr а также &arr указывает на одну и ту же ячейку памяти, но они оба имеют разные типы.
- arr имеет тип int* и распадается на указатель на первый элемент массива. Следовательно, любые знания о размере массива исчезли.
- &arr приводит к указателю типа int (*)[n] , то есть указатель на массив n целые Так, &arr указывает на весь массив и *(&arr + 1) (или же &arr)[1] ) указывает на следующий байт после массива.
Это работает благодаря тому, как работает арифметика указателей в C. Мы знаем, что указатель на int продвигается sizeof(int) при увеличении на 1. Точно так же указатель на int[n] продвигается sizeof(int[n]) , что является размером всего массива.
Как узнать размер массива переданного в функцию?
но в SIZE сохраняется 1, независимо от размера массива. Можно, конечно, вместе с массивом передать в функцию и его размер, но может существует более изящное решение? P.S.: Кстати, заметил нечто странное. Запускал эту программу через Visual Studio и Qt. В VS в SIZE сохраняется 1, а в Qt 2.
Отслеживать
44.8k 3 3 золотых знака 38 38 серебряных знаков 89 89 бронзовых знаков
задан 14 окт 2016 в 13:34
130 1 1 золотой знак 1 1 серебряный знак 8 8 бронзовых знаков
sizeof(Array) — размер указателя на int в данном случае.
14 окт 2016 в 13:37
При имеющейся сигнатуре размер массива Вы узнать не сможете.
14 окт 2016 в 13:38
А при чём тут C++? Размер массива в C++ узнать очень просто: методом size() (если это, скажем, vector ) или аналогичным.
14 окт 2016 в 13:40
@PinkTux так вопрос про обычные массивы, не STL-контейнеры же. Хотя согласен, в С++ по возможности стоит отказываться от сишных массивов в пользу vector, array и прочего.
14 окт 2016 в 13:42
Вот еще может помочь
14 окт 2016 в 13:42
2 ответа 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] )
В этом случае компилятор, используя шаблон, создаст столько функций, сколько массивов разной длины были использованы в качестве аргумента.
Как определить длину массива в C++
По сути, когда мы говорим о длине массива, мы имеем в виду общее количество элементов, присутствующих в соответствующем массиве. Например, посмотрите на массив ниже:
int array1[] =
Размер (или длина) массива равна общему количеству элементов в нем. Следовательно, в данном случае это «5».
Способы определения длины массива в C++
Теперь давайте посмотрим на различные способы, с помощью которых мы можем выяснить длину массива в C++:
- поэлементный подсчет,
- begin() и end(),
- функция sizeof(),
- функция size() в STL,
- указатели.
Теперь давайте обсудим каждый метод подробно и с примерами.
1: Поэлементный подсчет
Самый очевидный способ – перебрать заданный массив и одновременно подсчитать общее количество перебранных элементов.
Но если мы заранее не знаем длину массива для итерации, то в таком случае мы не можем использовать цикл for. Эту проблему можно решить, используя простой цикл for-each. Внимательно посмотрите на приведенный ниже код.
#include #include using namespace std; int main() < int c; int arr[]=; cout cout
Вы получите такой результат:
The array is: 1 2 3 4 5 6 7 8 9 0 The length of the given Array is: 10
Как мы говорили выше, здесь мы перебираем весь массив arr, используя цикл for-each с итератором i. Значение счетчика c увеличивается по мере итерации. Когда перебор закончится, в c вы найдете длину данного массива.
2: Функции begin() и end()
Мы также можем вычислить длину массива, используя стандартные функции begin() и end(). Эти две функции возвращают итераторы, указывающие на начало и конец массива соответственно. Внимательно посмотрите на данный код:
#include #include using namespace std; int main() < //Given Array int arr[] = < 11, 22, 33, 44 >; cout
Следовательно, разница между возвращаемыми значениями двух функций end() и begin() дает нам размер или длину данного массива. Данный код вернет:
The Length of the Array is : 4
3: Функция sizeof()
Оператор sizeof() в C++ возвращает размер переданной переменной или данных в байтах. Кроме того, он возвращает общее количество байтов, необходимых для хранения массива. Следовательно, если мы просто разделим размер массива на размер, занимаемый каждым его элементом, мы узнаем общее количество элементов, присутствующих в массиве.
Давайте посмотрим, как это работает:
#include #include using namespace std; int main() < //Given array int arr[] = ; int al = sizeof(arr)/sizeof(arr[0]); //length calculation cout
В результате мы получим:
The length of the array is: 3
4: Функция size() в STL
В стандартной библиотеке есть функция size(), которая возвращает количество элементов в заданном контейнере (в нашем случае это массив).
#include #include using namespace std; int main() < //Given array arrayarr< 1, 2, 3, 4, 5 >; //Using the size() function from STL cout
В результате вы получите:
The length of the given Array is: 5
5: Определение длины массива с помощью указателей
Узнать длину массива можно с помощью указателей. Давайте посмотрим, как это делается:
#include #include using namespace std; int main() < //Given array int arr[6] = ; int len = *(&arr + 1) - arr; //*(&arr + 1) is the address of the next memory location // just after the last element of the array cout
В результате мы получим:
The length of the array is: 6
Выражение *(arr+1) выдает адрес области памяти сразу после последнего элемента массива. Следовательно, разница между ним и начальным местоположением массива (или базовым адресом, arr) показывает общее количество элементов, присутствующих в данном массиве.
Заключение
Итак, в этом мануале мы обсудили различные методы определения длины массива в C++. Все приведенные выше методы просты в использовании, однако мы предпочитаем применять цикл for-each – не только из-за удобочитаемости кода, но и из-за его кросс-платформенной надежности.
Узнать размер массива по указателю
Всегда выодится 8. Не могу понять почему. В нете пишуть мутно либо — нельзя.
Так все-таки, можно узнать размер массива по указателю?
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Узнать размер памяти по указателю с помощью IntPtr.Size
Создаю объект IntPtr contourVs = CvInvoke.cvCreateMemStorage(0); //и выполняю с ним несколько.
Размер массива по указателю
Не уверен, что всё правильно понимаю. Про "new" пишут, что оно выделяет необходимое количество.
Определить размер массива по указателю
Собственно вопрос в следующем: можно ли определить размер выделенного динамически массива по.
Ушел с форума
16470 / 7433 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
Сообщение от animator404
Всегда выодится 8. Не могу понять почему.
Массив при передаче в функцию вырождается в указатель.
Т.е. «sizeof (args)» внутри printArrrSize случае всегда будет равен «sizeof (void *)».
Сообщение от animator404
Так все-таки, можно узнать размер массива по указателю?
Никак. Язык не предоставляет такой возможности.
21275 / 8292 / 637
Регистрация: 30.03.2009
Сообщений: 22,656
Записей в блоге: 30
Сообщение от animator404
Так все-таки, можно узнать размер массива по указателю?
В таких случаях есть два стандартных способа:
1. Размер передавать отдельным параметром
2. Последним элементом массива записывать специальное заранее оговоренное значение, которое функция будет трактовать как конец массива (при обходе всех элементов, начиная с первого)
В большинстве случаев пользуется первым
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь
Как узнать значение массива по указателю во время отладки?
А как посмотреть значения массива, если есть только указатель на его первый элемент? Например: .
Узнать размер массива
есть 2 указателя на первый элемент массива и указатель на элемент после последнего можно ли.
Как узнать размер массива?
Имею функцию template <typename T> int funk(T mas, T element) < //kod >
Узнать размер динамического массива
Здравствуйте. Пытаюсь сделать динамический массив и вывести его размерность. Выводится размерность.