2009-07-14 5 views
5

У меня есть массив C++ объявлен, как указано ниже:длина вычисления массива

CString carray[] = 
{ 
     "A", 
     "B", 
     "C", 
     "D", 
     "E" 
} 

Я хочу, чтобы определить длину carray во время выполнения. Я:

int iLength = sizeof(carray)/sizeof(CString); 

Это правильно?

+0

Да, я тоже поступаю так же, Как и вы, я жду, чтобы увидеть, есть ли другие способы. –

+0

Переименование этого вопроса на «Длина массива в C» может быть хорошей идеей. –

+3

Это не «определение» длины во время выполнения; длина является константой времени компиляции, и данное выражение является постоянным, поэтому компилятор может просто оценить его во время компиляции и подставить правильное значение. Кроме того, рассмотрите возможность отбрасывания скобок; sizeof не является функцией. – unwind

ответ

16

Да. В случае изменения типа объявленного элемента вы также можете написать

int iLength = sizeof(carray)/sizeof(carray[0]); 
+0

Это хорошо работает для C, но для C++ см. Ответ avakar для улучшенной альтернативы. Также рассмотрите использование неидиоматического упорядочения индекса массива, чтобы предотвратить получение потенциально некорректной информации от типов, которые перегружают оператор []: sizeof (array)/sizeof ([0]) –

+1

Вероятно, вы имели в виду 'sizeof (array)/sizeof (0 [массив]) '. :) Интригующая идея. – avakar

+1

Для небольшой драматизации используйте 'sizeof (array)/sizeof (* array)'. Легко запомнить тоже! – Saradhi

5

Этот код верный, но в большинстве случаев существуют лучшие способы обработки массивов на C++. Тем более, что этот метод не будет работать с массивами с динамическим размером.

Для таких случаев используйте стандартный класс библиотеки std::vector, который представляет массив динамического размера (т. Е. Вы можете вставлять и удалять записи).

+2

И boost :: array для статически размерных. – GManNickG

1

Да, это правильный способ сделать это, но он будет работать только в этой ситуации, когда размер массива известен во время компиляции и рассматривается на сайте инструкции sizeof(array). Он не будет работать с массивами с динамическим размером - вам понадобятся другие методы, например, использование контейнера типа stl :: vector или передача/сохранение количества элементов в качестве отдельного параметра.

0

Это не время выполнения, это время компиляции. То, как вы используете, правильно. Обратите внимание, что Visual Studio определяет функцию _countof, которая делает то же самое.

Во время выполнения длина не может быть определена. Вы либо сами сохраняете длину, либо используете std::vector

+0

Существующий код уже сохраняет длину массива. Но когда изменения массива (любой элемент удаляется из массива), я изменяю lengh массива. Я не могу использовать std: vector, потому что мне нужно его модифицировать во многих местах. –

+1

. Вектор не изменяется, когда вы удалите из него элемент. Также при выделении вектора возможно, что это не тот размер, который вы указали. –

0

Если у вас есть динамический массив, вероятно, вы должны использовать что-то вроде STL-вектора. http://www.cppreference.com/wiki/stl/vector/start

Нормальные массивы на C++ являются фиксированными, и вам необходимо вручную выделить память для расширения динамических.

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

+0

Я использую константу, но массив может меняться во время выполнения (любой элемент можно удалить или добавить). Если массив изменяется, я должен изменить значение константы. Я не могу использовать std: vector, потому что этот массив используется во многих местах. Пожалуйста, предложите некоторое обходное решение для этого –

+1

Почему вы не можете использовать «вектор»? Использовать его во многих местах - это не причина. Фактически, то же самое относится и к массиву C-стиля. –

+0

Не знаете, почему я был модифицирован, но вот некоторые основы для массивов: http://www.cplusplus.com/doc/tutorial/arrays/ – Glenn

24

Вы можете использовать следующий шаблон функции. Если вы используете Boost, вы можете позвонить по номеру boost::size.

template <typename T, std::size_t N> 
std::size_t size(T (&)[N]) 
{ 
    return N; 
} 

int iLength = size(carray); 

Как и другие уже говорили, однако, следует отдавать предпочтение std::vector в массивы C-стиле.

+3

+1 - чтобы было ясно, следует указать, что причина, по которой это следует использовать в C++ (очевидно, что она не будет работать на C), заключается в том, что она будет генерировать ошибку времени компиляции, если вы случайно попытаетесь использовать указатель, в то время как метод sizeof (ptr)/sizeof (ptr [0]) будет счастливо и молча давать неправильный результат. –

6

Это правильно, так как она использует метапрограммирование как это:

template <typename T, std::size_t N> 
inline std::size_t array_size(T (&)[N]) { 
    return N; 
}; 

Вы должны знать, что это работает, когда компилятор видит определение массива, но не после того, как он был передан в функцию (где он распадается на указатель):

void f(int array[]) 
{ 
    //std::cout << array_size(array) << std::endl; // fails, at this point array is a pointer 
    std::cout << sizeof(array)/sizeof(array[0]) << std::endl; // fails: sizeof(int*)/sizeof(int) 
} 
int main() 
{ 
    int array[] = { 1, 2, 3, 4, 5 }; 
    f(array); 
    std::cout << array_size(array) << std::endl; // 5 
    std::cout << sizeof(array)/sizeof(array[0]) << std::endl; // 5 
} 
+0

'inline' здесь избыточен. – avakar

+0

Лучший ответ в этой теме. – stepancheg

+1

@avakar: как и в большинстве мест, inline может быть либо ненужным, либо проигнорированным, в конце это просто предложение компилятору. Но он не является избыточным, компилятор не может решить, не генерировать функцию для каждого вызова в своем собственном праве (с или без встроенного, для чего важно), даже если большинство современных компиляторов будет встроить такую ​​небольшую функцию. –

0

Читать this статью Иван Дж Джонсон в доктора Доббс Journal. Я думаю, что он охватывает большинство представленных здесь решений. В нем также очень хорошо описаны достоинства и недостатки каждого подхода.

0

Windows SDK (т.е. windows.h заголовок) предлагает ARRAYSIZE макроса, который реализует эту функцию в безопасном способе (т.е. не работает с не-статическими массивами)

0

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

#define MAX_ROWS 1048 
int array[MAX_ROWS]; 

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

Смежные вопросы