Когда функция имеет параметр массива определенного размера, почему она заменяется указателем? - PullRequest
64 голосов
/ 25 августа 2009

Учитывая следующую программу,

#include <iostream>

using namespace std;

void foo( char a[100] )
{
    cout << "foo() " << sizeof( a ) << endl;
}

int main()
{
    char bar[100] = { 0 };
    cout << "main() " << sizeof( bar ) << endl;
    foo( bar );
    return 0;
}

выходы

main() 100
foo() 4
  1. Почему массив передается как указатель на первый элемент?
  2. Это наследие от C?
  3. Что говорит стандарт?
  4. Почему исключена строгая безопасность типов в C ++?

Ответы [ 3 ]

76 голосов
/ 25 августа 2009

Да, он унаследован от C. Функция:

void foo ( char a[100] );

Будет ли параметр настроен как указатель, и поэтому он становится:

void foo ( char * a );

Если вы хотите, чтобы тип массива был сохранен, вы должны передать ссылку на массив:

void foo ( char (&a)[100] );

C ++ '03 8.3.5 / 3:

... Тип функции определяется с использованием следующих правил. Тип каждого параметра определяется его собственным decl-specier-seq и декларатором. После определения типа каждого параметра любой параметр типа «массив из T» или «функция, возвращающая T» настраивается на «указатель на T» или «указатель на функцию, возвращающую T» соответственно ....

Чтобы объяснить синтаксис:

Проверьте правило "вправо-влево" в Google; Я нашел одно описание этого здесь .

Это будет применяться к этому примеру примерно следующим образом:

void foo (char (&a)[100]);

Начать с идентификатора 'a'

'a' - это

Двигайтесь вправо - мы находим ), поэтому мы меняем направление в поисках (. Двигаясь влево, мы проходим &

'a' является ссылкой

После & мы достигаем отверстия (, поэтому снова поворачиваем и смотрим направо. Теперь мы видим [100]

'a' является ссылкой на массив 100

И мы снова меняем направление, пока не достигнем char:

'a' - ссылка на массив из 100 символов

13 голосов
/ 25 августа 2009

Да. В C и C ++ вы не можете передавать массивы в функции. Так оно и есть.

Почему вы все равно делаете простые массивы? Вы смотрели на boost / std::tr1::array / std::array или std::vector?

Обратите внимание, что вы можете передать ссылку на массив произвольной длины в функцию template . С макушки головы:

template< std::size_t N >
void f(char (&arr)[N])
{
  std::cout << sizeof(arr) << '\n';
}
0 голосов
/ 21 декабря 2011

В терминологии C / C ++ есть великолепное слово, которое используется для статических массивов и указателей функций - decay . Рассмотрим следующий код:

int intArray[] = {1, 3, 5, 7, 11}; // static array of 5 ints
//...
void f(int a[]) {
  // ...
}
// ...
f(intArray); // only pointer to the first array element is passed
int length = sizeof intArray/sizeof(int); // calculate intArray elements quantity (equals 5)
int ptrToIntSize = sizeof(*intArray); // calculate int * size on your system
...