Размер массива С++
Возможный дубликат:
Размер массива, переданный как параметр
Мне было интересно, почему вывод следующего кода равен 1 и 9. Это из-за необъявленного массива в размере функции? Как я могу отделить "размер массива" к функции?
#include "stdafx.h"
#include <iostream>
using namespace std;
int size(int a[])
{
return sizeof a/sizeof a[0];
}
int main()
{
int a[] = {5,2,4,7,1,8,9,10,6};
cout << size(a) << endl;
cout << sizeof a/sizeof a[0] << endl;
system("pause");
return 0;
}
Ответы
Ответ 1
Когда вы пишете size(a)
, вы передаете указатель, а не массив. Поскольку размер указателя и int
равен 4 или 8 (в зависимости от ABI), вы получаете sizeof(int *)/sizeof int
( 4/4 = 1 для 32-разрядных машин и 8/4 = 2 для 64-битных), 1 или 2.
В С++ при передаче массива в качестве аргумента функции фактически передается указатель на массив.
Ответ 2
Ответ Maroun85 правильный. Это не очевидно, но a
в int size(int a[])
является указателем.
Но почему бы вам не сделать это С++. Используя std::vector
s
std::vector<int> a = {5,2,4,7,1,8,9,10,6};
cout << a.size() << endl;
здесь нет трюков
- отредактировать
Если ваш компилятор не поддерживает С++ 11. Вы можете сделать:
std::vector<int> a;
a.push(5);
a.push(2);
...
cout << a.size() << endl;
Ответ 3
Ваша функция size()
не может работать так, как вы хотите, потому что, когда вы передаете массив функции, массив распадается на указатель на свой первый элемент. Ваши распады a
для оператора int*
и sizeof на указателе возвращают размер указателя, а не массив. Рассмотрите возможность использования std::vector<int>
, так как это позволит вам получать размер вектора каждый раз, когда вы передаете его функции.
Ответ 4
При передаче массивов в функции они распадаются на указатели. Итак, ваша функция size()
эквивалентна:
int size(int* a)
{
return sizeof a/sizeof a[0];
}
И sizeof a
- это размер указателя, который является таким же, как размер int здесь, следовательно, выход.
Ответ 5
Помните, что массив всегда передается указателем.
Таким образом, в функции a
есть указатель на int
, и (для 32-битных интерлееров) размер указателя на int
совпадает с размером int
.
Ответ 6
sizeof
оценивается во время компиляции, а не во время выполнения. Компилятор не анализирует, что вы передаете функции size
, а скорее рассматривает параметр функции как указатель. Таким образом, в вашей функции size
результатом sizeof a
является размер указателя на int
, который, случайно, равен размеру int
в вашей системе.
Ответ 7
Лучшее объяснение, почему ваше решение не работает, - это ответ Маруна.
О второй части вопроса ( "как это можно сделать?" ), вы можете сделать это с помощью функции шаблона:
template <typename T, size_t n> const size_t size(const T (&)[n]) { return n; }
Конечно, это работает только в том случае, если размер массива постоянный (постоянный, как видно компилятору), но в любом случае он может работать только в этом случае - массив не сохраняет его размер нигде, поэтому, если это не известная константа времени компиляции, нет способа узнать ее.
Если вам нужно это для работы с массивами, которые не являются константами времени компиляции (например, что-то, что вы выделяете с помощью operator new[]
или с использованием нестандартного расширения компилятора), вам нужно явно хранить размер где-то.
(Кстати, мой вышеприведенный вывод технически неверен, действительно, размер распределения обычно сохраняется, но это детали реализации, от которых вы не можете и не должны зависеть.)