Почему функция не знает размер массива? - PullRequest
1 голос
/ 01 мая 2010

Если я напишу

int main()
{
    int a[100] = {1,2,3,4,};
    cout<<sizeof(a)/sizeof(a[0])<<endl; //a is a pointer to the first elem of array, 
                                        //isn't it
    return 0;
}

Я получаю 400!

Если я напишу

void func (int * a);

int main()
{
    int a[100] = {1,2,3,4,};
    func(a);
    return 0;
}

void func(int *a)
{
     cout<<sizeof(a)/sizeof(a[0])<<endl; //a is a pointer to the first elem of array
}

Тогда я получу 1!

Так почему функция не знает размер массива?

Ответы [ 8 ]

5 голосов
/ 01 мая 2010

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

1 голос
/ 25 мая 2010

При передаче вашего массива в качестве параметра функции, принимающей указатель, массив затухает как указатель.

void bar(int *a)
{
    std::cout << sizeof(a) << std::endl; // outputs "4" (on a 32 bit compiler)
}

void foo()
{
    int a[100] ;
    std::cout << sizeof(a) << std::endl; // outputs "400" (on a 32 bit compiler)
    bar(a);
}

Так что, возможно, решение состоит в том, чтобы предоставить правильную функцию, принимающую ссылку на массив в качестве параметра:

template <size_t T_Size>
void bar(int (&a)[T_Size])
{
    std::cout << T_Size << std::endl;    // outputs "100" (on ALL compilers)
    std::cout << sizeof(a) << std::endl; // outputs "400" (on a 32 bit compiler)
}

void foo()
{
    int a[100] ;
    std::cout << sizeof(a) << std::endl; // outputs "400" (on a 32 bit compiler)
    bar(a);
}

Конечно, функция должна быть шаблонной.

1 голос
/ 02 мая 2010

Это не работает, потому что sizeof рассчитывается во время компиляции. Функция не имеет информации о размере своего параметра (она знает только, что она указывает на адрес памяти).

Рассмотрите возможность использования вектора STL или передачи размеров массива в качестве параметров для функций.

На это ответил Марсель Гузман в Расчет размера массива !

1 голос
/ 01 мая 2010

sizeof возвращает размер типа. Во втором примере func( int *a ), a является указателем, и sizeof сообщит об этом как таковой. Даже если вы сделали func( int a[100] ), указатель был бы. Если вам нужен размер массива в func, вы должны передать его в качестве дополнительного аргумента.

0 голосов
/ 28 июля 2010

Функция не знает размер массива в вашем примере, потому что вы предприняли явные шаги для преобразования массива в тип указателя, таким образом полностью удалив параметр функции из его первоначальной природы массива. Еще раз, вы сами предприняли осознанные шаги, чтобы убедиться, что функция не знает размер массива. В этих условиях довольно странно видеть, что вы задаете вопрос о том, почему функция не знает размер массива.

Если вы хотите, чтобы функция получила свой аргумент в виде массива , вы должны передать ее в виде массива , а не просто как указатель, и соответственно объявить соответствующий параметр функции , Массивы в C ++ не могут быть переданы «по значению», что означает, что вам придется передавать его «по ссылке», как одну возможность

void func(int (&a)[100])
{
  cout << sizeof a / sizeof a[0] << endl;
}
0 голосов
/ 01 мая 2010

Указатель является указателем. Это означает, что это просто указывает на память, и это все об этом. Создание указателя на массив (что обычно означает указатель на первый элемент массива, но не обязательно) все еще является только указателем на некоторую ячейку памяти. Поскольку адрес памяти - это просто адрес памяти, указатель также не может знать, что память, на которую он указывает, изначально был массивом, или как долго этот массив был.

Это просто, как работают указатели. Они указывают на память, и все.

0 голосов
/ 01 мая 2010

Вы получаете 400 в первый раз, потому что вы передаете только sizeof (a), а не sizeof (a) / sizeof (a [0]), cout. Вам нужно заключить этот расчет в круглые скобки, чтобы получить правильное значение, например:

cout << (sizeof(a)/sizeof(a[0])) << endl;

Во второй раз вы должны получить 2, 4 или 8 (в зависимости от архитектуры), определенно не 400, поскольку вы по сути выводите это:

cout << sizeof(int*) << endl;

Где размер универсального указателя всегда является фиксированным значением.

0 голосов
/ 01 мая 2010

Нет. Вы не правы.

Если я запускаю вторую часть кода, она дает 1 на моем компьютере. Это не 400.

#include <iostream>

void func(int *a);

using namespace std;

int main()
{
    int a[100] = {1,2,3,4,};
    func(a);
    return 0;
}

void func(int *a)
{
     cout<<sizeof(a)/sizeof(a[0])<<endl;
}

Производит

1
...