Возможный дубликат:
Размер массива передается как параметр
Мне было интересно, почему вывод следующего кода 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;
}
Когда ты пишешь size(a)
тогда вы передаете указатель, а не массив. Поскольку размер указателя и int
4 или 8 (в зависимости от ABI), вы получаете sizeof(int *)/sizeof int
(4/4 = 1 для 32-битных машин и 8/4 = 2 для 64-битных), что 1 или же 2.
В C ++, когда массив передается в качестве аргумента функции, фактически вы передаете указатель на массив.
Maroun85 ответ правильный. Это не очевидно, но a
в int size(int a[])
это указатель
Но почему бы вам не сделать это способом C ++. С помощью std::vector
s
std::vector<int> a = {5,2,4,7,1,8,9,10,6};
cout << a.size() << endl;
здесь нет трюков
— редактировать
Если ваш компилятор не поддерживает c ++ 11. Ты можешь сделать:
std::vector<int> a;
a.push(5);
a.push(2);
...
cout << a.size() << endl;
Ваш size()
функция не может работать так, как вы хотите, потому что когда вы передаете массив функции, массив распадается на указатель на свой первый элемент. Ваш a
распадается на int*
и оператор sizeof для указателя возвращает размер указателя, а не массива. Рассмотрите возможность использования std::vector<int>
вместо этого, поскольку это позволит вам получать размер вектора каждый раз, когда вы передаете его функции.
При передаче массивов в функции они распадаются на указатели. Так что ваши size()
функция эквивалентна:
int size(int* a)
{
return sizeof a/sizeof a[0];
}
А также sizeof a
это размер указателя, который равен размеру int здесь, отсюда вывод.
sizeof
оценивается во время компиляции, а не во время выполнения. Компилятор не анализирует то, что вы передаете функции size
, а скорее обрабатывает параметр функции как указатель. Таким образом, в вашей функции size
результат sizeof a
это размер указатель для int
, который, случайно, равен размеру int
в вашей системе.
Помните, что массив всегда передается по указателю.
Так в функции a
это указатель на int
и (для 32-битных интервалов) размер указателя на int
одинакового размера int
,
Лучшее объяснение того, почему ваше решение не работает, — ответ Маруна.
Что касается второй части вопроса («как это можно сделать?»), Вы можете сделать это с помощью функции шаблона:
template <typename T, size_t n> const size_t size(const T (&)[n]) { return n; }
Конечно, это работает, только если размер массива постоянен (постоянен, как это видно из компилятора), но в любом случае он может работать только в этом случае — массив нигде не хранит свой размер, поэтому, если он не известная константа времени компиляции, нет способа узнать это.
Если вам нужно это для работы с массивами, которые не константы времени компиляции (скажем, то, что вы выделяете с operator new[]
или используя нестандартное расширение компилятора), вам нужно явно где-то хранить размер.
(Кстати, мое вышеупомянутое утверждение технически неправильно, действительно, размер выделения обычно сохраняется, но это деталь реализации, от которой вы не можете и не должны зависеть.)