2011-01-23 2 views
4

Как я хочу найти размер массива динамически в функции, я использовал оператор sizeof. Но я получил неожиданный результат. вот одна демо-программа, чтобы показать вам, что я хочу делать.проблема с оператором sizeof

//------------------------------------------------------------------------------------------ 
#include <iostream> 

void getSize(int *S1){ 

    int S_size = sizeof S1/sizeof(int); 
    std::cout<<"array size(in function):"<<S_size<<std::endl; 
} 

int main(){ 

    int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6}; 
    getSize(S); 
    std::cout<<"array size:"<<sizeof S/sizeof(int)<<std::endl; 
    return 0; 
} 
//------------------------------------------------------------------------------------------ 

компиляции команда: г ++ demo1.cc -o demo1 {12} мягкая фетровая

выход:

array size(in function):2 
array size:19 

пожалуйста, объясните, почему это происходит. что можно сделать для решения этой проблемы.

+1

Прочтите [это] (http://stackoverflow.com/questions/1975128/sizeof-an-array-in-the-c-programming-language/1975133#1975133) ответ и [это] (http: // stackoverflow.com/questions/2384107/magic-arguments-in-function-templates). –

+2

Хороший пример того, почему массивы не являются указателями. – Oystein

ответ

9
void getSize(int *S1) 

Когда вы передаете массив для этой функции, он распадается на указатель типа, так sizeof оператор возвращает размер указателя.

Однако, вы определяете функцию, как,

template<int N> 
void getSize(int (&S1)[N]) 
{ 
    //N is the size of array 
    int S_size1 = N; 
    int S_size2 = sizeof(S1)/sizeof(int); //would be equal to N!! 
    std::cout<<"array size(in function):"<<S_size1<<std::endl; 
    std::cout<<"array size(in function):"<<S_size2<<std::endl; 
} 

int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6}; 
getSize(S); //same as before 

, то вы можете иметь размер массива, в функции!

Смотрите демонстрацию сами здесь: http://www.ideone.com/iGXNU

+3

+1 для шаблонов – Marlon

+1

спасибо .. работа совершенно. –

0

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

3

Внутри getSize(), вы получаете размер указателя, который 8 байт (так как вы, вероятно, работает 64-разрядная ОС). В main() вы получаете размер массива.

Если вы хотите узнать размер массива, передайте результат sizeof(S) в качестве дополнительного аргумента getSize().

Другие альтернативы будут использовать некоторый контейнер (например, std::vector) или функцию поворота в функцию шаблона, как предлагал Наваз.

+0

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

0

Вам нужно будет передать размер массива функции.

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

void getSize(int *S1, size_t size) 
{ 
    int S_Size = sizeof(*S1) * size; 
} 

Это является излишним, хотя, если вы об этом думаете: D

0

S является int *, указатель на целое число, которое является адресом памяти, который находится на вашей машине в два раза размера целое число.

Если вы хотите размер массива (Ie, количество элементов), вы не можете получить его непосредственно в чистом C. Но поскольку это вопрос C++, существует способ: используйте vector, который имеет метод size().

На самом деле, это не совсем верно: в функции, что вы объявляете S (и только если это явно инициализирована во время компиляции, как вы в вашем примере - даже new int[19] не работает), то sizeof оператор фактически делает получить правильный ответ, поэтому C++ позволяет сделать это:

int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6}; 
vector<int> v(S, S + sizeof(S)/sizeof(int)); 

, а затем вы можете использовать v.size() (см these docs).

версия шаблон Наваз в других местах является еще одним отличным предложением, которое заставляет компилятор в несущий полную информацию о построении C++ массива вокруг (опять же, обратите внимание, что это все известные в время компиляции, поэтому вам может быть явно о размере в аргументе).

0

Для предотвращения такого случайного злоупотребления SizeOf, вы можете определить функцию, которая работает только на массивах:

template<class T, int N> 
int array_size(T (&)[N]) { 
    return N; 
} 

Если вы используете это в вашем коде, вы увидите сообщение об ошибке компилятора применительно к S1, поскольку это не массив. Кроме того, он короче и немного более явный, чем sizeof array/sizeof array [0] (используя размер первого элемента означает, что вам не нужно повторять тип массива).

Это также уже существует в Boost в более общей форме (принимая что-либо с помощью метода размера, такого как std :: vector).

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