Когда функция имеет параметр массива определенного размера, почему она заменяется указателем?
Учитывая следующую программу,
#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
- Почему массив передается как указатель на первый элемент?
- Это наследие от C?
- Что говорит стандарт?
- Почему существует строгая безопасность типа С++?
Ответы
Ответ 1
Да, он унаследован от C. Функция:
void foo ( char a[100] );
Будет настроен параметр как указатель, и он станет следующим:
void foo ( char * a );
Если вы хотите сохранить тип массива, вы должны передать ссылку на массив:
void foo ( char (&a)[100] );
С++ '03 8.3.5/3:
... Тип функции определяется с использованием следующих правил. Тип каждого параметра определяется из его собственного decl-specifier-seq и declarator. После определения типа каждого параметра любой параметр типа "массив T" или "возвращающая функцию T" настраивается как "указатель на T" или "указатель на функцию возврата T" соответственно....
Чтобы объяснить синтаксис:
Проверьте правильность "правого левого" правила в google; Я нашел одно описание здесь.
Он будет применяться к этому примеру примерно следующим образом:
void foo (char (&a)[100]);
Начните с идентификатора 'a'
'a' является
Переместитесь вправо - мы найдем )
, чтобы мы обратном направлении искали (
. Когда мы двигаемся влево, мы проходим &
'a' является ссылкой
После &
мы дойдем до открытия (
, чтобы мы снова обратились и посмотрим правильно. Теперь мы видим [100]
'a' является ссылкой на массив из 100
И мы снова поворачиваем направление, пока не достигнем char
:
'a' - ссылка на массив из 100 символов
Ответ 2
Да. В C и С++ вы не можете передавать массивы в функции. Это так, как есть.
Почему вы все равно делаете простые массивы? Вы посмотрели на boost
/std::tr1::array
/std::array
или std::vector
?
Обратите внимание, что вы можете передать ссылку на массив произвольной длины на шаблон функции. Сверху моей головы:
template< std::size_t N >
void f(char (&arr)[N])
{
std::cout << sizeof(arr) << '\n';
}
Ответ 3
В терминологии C/С++ есть великолепное словосочетание, которое используется для статических массивов и указателей функций - распад.
Рассмотрим следующий код:
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