Количество элементов массива в С++
Скажем, у меня есть массив arr
. Когда следующее не даст количество элементов массива: sizeof(arr) / sizeof(arr[0])
?
Я могу только один случай: массив содержит элементы, которые имеют разные производные типы типа массива.
Я прав, и там (я почти уверен, что должны быть) другие такие случаи?
Извините за тривиальный вопрос, я разработчик Java, и я довольно новичок в С++.
Спасибо!
Ответы
Ответ 1
Скажем, у меня есть массив arr. когда будет ли следующее количество элементов массива: sizeof (arr)/sizeof (arr [0])?
Одна вещь, которую я часто видел, когда это делают новые программисты:
void f(Sample *arr)
{
int count = sizeof(arr)/sizeof(arr[0]); //what would be count? 10?
}
Sample arr[10];
f(arr);
Итак, новые программисты считают, что значение count
будет 10. Но это неправильно.
Даже это неверно:
void g(Sample arr[]) //even more deceptive form!
{
int count = sizeof(arr)/sizeof(arr[0]); //count would not be 10
}
Все потому, что как только вы передаете массив любой из этих функций, он становится типом указателя, поэтому sizeof(arr)
будет указывать размер указателя, а не массива.
EDIT:
Ниже представлен элегантный способ передать массив функции, не позволяя ему распадаться на тип указателя:
template<size_t N>
void h(Sample (&arr)[N])
{
size_t count = N; //N is 10, so would be count!
//you can even do this now:
//size_t count = sizeof(arr)/sizeof(arr[0]); it'll return 10!
}
Sample arr[10];
h(arr); //pass : same as before!
Ответ 2
Массивы на С++ сильно отличаются от массивов на Java, поскольку они полностью неуправляемы. Компилятор или время выполнения не имеют представления о том, какой размер массива.
Информация известна только во время компиляции, если размер определяется в объявлении:
char array[256];
В этом случае sizeof (array) дает вам правильный размер.
Если вы используете указатель как массив, то "array" будет просто указателем, а sizeof не даст вам никакой информации о фактическом размере массива.
STL предлагает множество шаблонов, которые позволяют иметь массивы, некоторые из которых имеют информацию о размере, некоторые из них с переменными размерами, и большинство из них имеют хорошие проверки доступа и ограничений.
Ответ 3
Нет случаев, когда массив arr
, если значение sizeof(arr) / sizeof(arr[0])
не является числом элементов, по определению массива и sizeof
.
Фактически, он даже прямо упоминается (§5.3.3/2):
.... При применении к массиву результатом является общее количество байтов в массиве. Это означает, что размер массива из n элементов в n раз превышает размер элемента.
Акцент мой. Разделите размер элемента, sizeof(arr[0])
, чтобы получить n.
Ответ 4
Нет, это все равно даст правильное значение, потому что вы должны определить массив как все элементы одного типа или указатели на тип. В любом случае размер массива известен во время компиляции, поэтому sizeof (arr)/sizeof (arr [0]) всегда возвращает счетчик элементов.
Вот пример правильного использования:
int nonDynamicArray[ 4 ];
#define nonDynamicArrayElementCount ( sizeof(nonDynamicArray) / sizeof(nonDynamicArray[ 0 ]) )
Далее я расскажу, когда использовать это правильно. Вы не будете использовать его очень часто. Это в первую очередь полезно, когда вы хотите определить массив специально, чтобы вы могли добавлять к нему элементы, не изменяя при этом много кода. Это конструкция, которая в первую очередь полезна для обслуживания. Канонический пример (когда я думаю об этом в любом случае;-) строит таблицу команд для некоторой программы, которую вы намерены добавить позже. В этом примере для поддержания/улучшения вашей программы все, что вам нужно сделать, это добавить еще одну команду в массив, а затем добавить обработчик команд:
char *commands[] = { // <--- note intentional lack of explicit array size
"open",
"close",
"abort",
"crash"
};
#define kCommandsCount ( sizeof(commands) / sizeof(commands[ 0 ]) )
void processCommand( char *command ) {
int i;
for ( i = 0; i < kCommandsCount; ++i ) {
// if command == commands[ i ] do something (be sure to compare full string)
}
}
Ответ 5
Во-первых, вы можете обойти эту проблему, используя std::vector
вместо массива. Во-вторых, если вы поместите объекты производного класса в массив суперкласса, вы испытаете нарезку, но хорошая новость заключается в том, что ваша формула будет работать. Полиморфные коллекции в С++ достигаются с помощью указателей. Здесь есть три основных варианта:
Ответ 6
Скажем, у меня есть массив arr. Когда следующее не даст количество элементов массива: sizeof(arr) / sizeof(arr[0])
?
В контекстах, где arr
на самом деле не массив (но вместо этого указатель на исходный элемент). Другие ответы объясняют, как это происходит.
Я могу только один случай: массив содержит элементы, которые имеют разные производные типы типа массива.
Этого не может произойти (по сути, по той же причине, что Java-массивы не очень хорошо сочетаются с дженериками). Массив статически типизирован; он резервирует "слоты" памяти, которые имеют размер для определенного типа (базовый тип).
Извините за тривиальный вопрос, я разработчик Java, и я довольно новичок в С++.
Массивы С++ не являются первоклассными объектами. Вы можете использовать boost:: array, чтобы заставить их вести себя скорее как массивы Java, но имейте в виду, что у вас все еще будет семантика значений, а не ссылочная семантика, как и все остальное. (В частности, это означает, что вы не можете действительно объявить переменную типа, аналогичную Foo[]
в Java, и не заменять массив другим другим размером, размер массива является частью этого типа.) Используйте .size()
с этим классом, где вы бы использовали .length
в Java. (Он также предоставляет итераторы, которые обеспечивают обычный интерфейс для итераторов С++.)
Ответ 7
Используйте макрос Microsoft "_countof (массив)". Эта ссылка на Сеть разработчиков Microsoft объясняет это и предлагает пример, демонстрирующий разницу между "sizeof (array)" и макросом "_countof (array)".
Microsoft и "_countof (array)" Macro
Ответ 8
_countof (my_array) в MSVC
Я могу только один случай: массив содержит элементы, которые имеют разные производные типы типа массива.
Элементы массива в С++ являются объектами, а не указателями, поэтому вы не можете иметь объект производного типа как элемент.
И как уже упоминалось выше, sizeof (my_array) (например, _countof()) будет работать только в области определения массива.
Ответ 9
/* Я не совсем уверен, что понял вопрос, но вот что я понял. У вас есть массив с элементами, и вы хотите узнать, сколько элементов в массиве? Вот что я сделал *
int myArray [] = {B00011101, B00011011}//два элемента в массиве int Elements; // переменная, в которой мы будем хранить количество элементов в данном массиве
пустая функция(){
/* Elements = sizeof (myArray); Это дало мне результат 4, поэтому я подумал, что, возможно, мне нужно разделить его на 2, поэтому я ввел еще один элемент в массив, чтобы у меня было 3 элемента "int myArray [] = {B00011101, B00011011, B00011011}" и переменная If. Элементы дает мне номер 6, мое решение будет работать, и оно действительно показало мне номер 6, что означало, что количество элементов по некоторым причинам умножено на 2, так что в основном я сделал, я разделил его на 2 *
Elements = sizeof (myArray)/2;/* также я делал это в компиляторе arduino, не уверен, работает ли он в обычном компиляторе c++, но он должен работать. */
}
Ответ 10
Я знаю старую тему, но как насчет простого решения вроде цикла while?
int function count(array[]) {
int i = 0;
while(array[i] != NULL) {
i++;
}
return i;
}
Я знаю, что это медленнее, чем sizeof(), но это еще один пример подсчета массива.