当函数具有特定大小的数组参数时,为什么它被指针替换?

CsT*_*mas 65 c++ arrays standards sizeof function-parameter

鉴于以下计划,

#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;
}
Run Code Online (Sandbox Code Playgroud)

输出

main() 100
foo() 4
Run Code Online (Sandbox Code Playgroud)
  1. 为什么数组作为指向第一个元素的指针传递?
  2. 它是C的遗产吗?
  3. 标准说什么?
  4. 为什么C++的严格类型安全性下降了?

Ric*_*den 78

是的,它继承自C.功能:

void foo ( char a[100] );
Run Code Online (Sandbox Code Playgroud)

将参数调整为指针,因此变为:

void foo ( char * a );
Run Code Online (Sandbox Code Playgroud)

如果您希望保留数组类型,则应传入对该数组的引用:

void foo ( char (&a)[100] );
Run Code Online (Sandbox Code Playgroud)

C++ '03 8.3.5/3:

...使用以下规则确定函数的类型.每个参数的类型由其自己的decl-specifier-seq和声明符确定.在确定每个参数的类型之后,将"T的数组"或"返回的函数T"的任何参数分别调整为"指向T的指针"或"指向返回T的函数的指针"....

解释语法:

检查谷歌中的"右 - 左"规则; 我在这里找到了一个描述.

它将大致如下应用于此示例:

void foo (char (&a)[100]);
Run Code Online (Sandbox Code Playgroud)

从标识符'a'开始

'a'是一个

向右移动 - 我们发现了一个)反方向寻找的方向(.当我们向左移动时,我们通过&

'a'是一个参考

&我们到达开口后(,我们再次反转,看起来正确.我们现在看到了[100]

'a'是对100的数组的引用

我们再次反向,直到达到char:

'a'是对100个字符数组的引用

  • 这归结为C/C++中的普通数组参数是虚构的事实 - 它们确实是指针.应尽可能避免数组参数 - 它们实际上只是混淆了问题. (5认同)
  • 值得一提的是,使用std :: vector将巧妙地解决与传递数组相关的所有问题. (4认同)
  • 只是挑剔:函数参数不会衰减到指针.它被*调整为指针.如果函数参数是指针,则用作函数*参数*的数组名称可以*衰减*到指针. (2认同)
  • 非常感谢解释规则,因为链接现在是 404。 (2认同)

sbi*_*sbi 13

是.在C和C++中,您无法将数组传递给函数.就是那样子.

你为什么要做普通阵列呢?你看过boost/ std::tr1::array/ std::arraystd::vector

但请注意,您可以将对任意长度的数组的引用传递给函数模板.脱离我的头顶:

template< std::size_t N >
void f(char (&arr)[N])
{
  std::cout << sizeof(arr) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

  • 但是你可以传入"数组引用". (6认同)
  • 通过引用传递给数组不限于"函数模板".您可以通过引用非模板函数来传递数组.使用函数模板的优点是可以推导出数组索引,从而允许您可以为不同大小的数组类型调用函数. (5认同)
  • @CsTamas,是的,传递数组和对象的规则在C中是不同的.当作为参数传递时,结构实际上是按值复制的.数组被视为指向其第一个元素的指针.(C中的数组和指针非常相互关联.它们不是一回事,但为了参数传递,它们是相同的) (3认同)
  • 或者只是`std :: cout << N;`:) (3认同)