Как найти размер int []? - PullRequest
       23

Как найти размер int []?

39 голосов
/ 10 января 2010

у меня

int list[] = {1, 2, 3};

Как мне получить размер list?

Я знаю, что для массива символов мы можем использовать strlen(array), чтобы найти размер, или проверить с помощью '\0' в конце массива.


Я пытался sizeof(array) / sizeof(array[0]), как сказали некоторые ответы, но он работает только в основном? Например:

int size(int arr1[]){
    return sizeof(arr1) / sizeof(arr1[0]);
}

int main() {
    int list[] = {1, 2, 3};

    int size1 = sizeof(list) / sizeof(list[0]); // ok
    int size2 = size(list_1); // no
    // size1 and size2 are not the same
}

Почему?

Ответы [ 11 ]

50 голосов
/ 10 января 2010

Попробуйте это:

sizeof(list) / sizeof(list[0]);

Поскольку этот вопрос помечен как C ++, всегда рекомендуется использовать std::vector в C ++ вместо использования обычных массивов в стиле C.


array-type неявно преобразуется в pointer-type при передаче его функции. Посмотрите на это.

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

Вы бы сделали это так для общего случая

template<typename T,int N> 
//template argument deduction
int size(T (&arr1)[N]) //Passing the array by reference 
{
   return sizeof(arr1)/sizeof(arr1[0]); //Correctly returns the size of 'list'
   // or
   return N; //Correctly returns the size too [cool trick ;-)]
}
12 голосов
/ 10 января 2010

«Стандартный» способ C сделать это -

sizeof(list) / sizeof(list[0])
9 голосов
/ 10 января 2010

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

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

Обратите внимание, что если вы хотите использовать размер в качестве константного выражения, вам придется использовать идиому sizeof a / sizeof a[0] или дождаться следующей версии стандарта C ++.

8 голосов
/ 10 января 2010

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

#define COUNTOF(x) (sizeof(x)/sizeof(*x))

Чтобы получить размер динамического массива, вы должны отслеживать его вручную и передавать его вместе с ним, или завершать его с помощью значения часового типа (как '\ 0' в строках с нулевым символом в конце).

Обновление: Я понял, что ваш вопрос помечен C ++, а не C. Вам определенно следует рассмотреть возможность использования std::vector вместо массивов в C ++, если вы хотите обойти все вокруг:

std::vector<int> v;
v.push_back(1);
v.push_back(2);
std::cout << v.size() << std::endl; // prints 2
4 голосов
/ 10 января 2010

Поскольку вы пометили это как C ++, стоит упомянуть, что есть несколько лучший способ, чем макрос в стиле C:

template <class T, size_t N>
size_t countof(const T &array[N]) { return N; }

Это имеет то преимущество, что если вы случайно попытаетесь передать ему что-то, кроме массива, код просто не скомпилируется (тогда как передача указателя на макрос C скомпилирует, но даст плохой результат. Недостатком является то, что это не дает вам константу времени компиляции, поэтому вы не можете сделать что-то вроде этого:

int a[20];

char x[countof(a)];

В C ++ 11 или новее вы можете добавить constexpr, чтобы получить постоянную времени компиляции:

template <class T, size_t N>
constexpr size_t countof(const T &array[N]) { return N; }

Если вы действительно хотите поддерживать то же самое на старых компиляторах, есть способ, изначально изобретенный Иваном Джонсоном, AFAIK:

#define COUNTOF(x)  (                                           \
  0 * sizeof( reinterpret_cast<const ::Bad_arg_to_COUNTOF*>(x) ) +  \
  0 * sizeof( ::Bad_arg_to_COUNTOF::check_type((x), &(x))      ) +  \
  sizeof(x) / sizeof((x)[0])  )                                  


class Bad_arg_to_COUNTOF
{
public:
   class Is_pointer;
   class Is_array {};  
   template<typename T>
   static Is_pointer check_type(const T*, const T* const*);
   static Is_array check_type(const void*, const void*);
};

При этом используется sizeof (x) / sizeof (x [0]) для вычисления размера, как это делает макрос C, поэтому он дает константу времени компиляции. Разница в том, что он сначала использует шаблонную магию, чтобы вызвать ошибку компиляции, если то, что вы передали, не является именем массива. Это происходит путем перегрузки check_type для возврата неполного типа для указателя, но полного типа для массива. Затем (действительно сложная часть) он вообще не вызывает эту функцию - он просто принимает размер типа, который должна возвращать функция, который равен нулю для перегрузки, которая возвращает полный тип, но не разрешается (форсируя ошибка компиляции) для неполного типа.

IMO, это довольно крутой пример шаблонного метапрограммирования - хотя, честно говоря, результат вроде бессмысленный. Вам действительно нужен этот размер в качестве постоянной времени компиляции, если вы используете массивы, которых в любом случае следует избегать. Используя std::vector, можно указывать размер во время выполнения (и изменять размер вектора, когда / при необходимости).

4 голосов
/ 10 января 2010

Помимо ответа Карла, "стандартный" способ C ++ - это не использовать массив C int, а что-то вроде C ++ STL std::vector<int> list, который можно запросить для list.size().

1 голос
/ 10 января 2010

когда вы передаете любой массив какой-либо функции.Вы просто передаете его начальный адрес, так что для его работы вам нужно передать его размер, чтобы он работал правильно.это та же самая причина, по которой мы передаем argc с argv [] в аргументе командной строки.

0 голосов
/ 04 ноября 2018

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

Вот мой фрагмент кода

template <typename TypeOfData>


void PrintArray(TypeOfData &arrayOfType);

int main()

{

    char charArray[] = "my name is";

    int intArray[] = { 1,2,3,4,5,6 };

    double doubleArray[] = { 1.1,2.2,3.3 };


    PrintArray(charArray);

    PrintArray(intArray);

    PrintArray(doubleArray);

}


template <typename TypeOfData>

void PrintArray(TypeOfData &arrayOfType)

{

    int elementsCount = sizeof(arrayOfType) / sizeof(arrayOfType[0]);


    for (int i = 0; i < elementsCount; i++)

    {

        cout << "Value in elements at position " << i + 1 << " is " << arrayOfType[i] << endl;

    }

}
0 голосов
/ 11 мая 2018

Этот метод работает, когда вы используете класс: в этом примере вы получите массив, поэтому единственный метод, который работал для меня, был таким:

template <typename T, size_t n, size_t m>   
Matrix& operator= (T (&a)[n][m])
{   

    int arows = n;
    int acols = m;

    p = new double*[arows];

    for (register int r = 0; r < arows; r++)
    {
        p[r] = new double[acols];


        for (register int c = 0; c < acols; c++)
        {
            p[r][c] = a[r][c]; //A[rows][columns]
        }

}

https://www.geeksforgeeks.org/how-to-print-size-of-an-array-in-a-function-in-c/

0 голосов
/ 13 марта 2018
int arr1[] = {8, 15, 3, 7};
int n = sizeof(arr1)/sizeof(arr1[0]);

Таким образом, sizeof (arr1) дает размер объекта, на который указывает указатель, каждый элемент может занимать несколько битов, поэтому деление на количество бит на элемент (sizeof (arr1 [0]) дает фактическое количество элементов вы ищете, т.е. 4 в моем примере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...