按值传递typedef(固定大小)数组

时间:2011-05-17 16:21:13

标签: c++ arrays typedef

我很难理解数组的typedef模式。

typedef char Char10[10];
void fun (Char10 a)  // not passing reference (interested in pass by value)
{
  if(typeid(Char10) == typeid(char*))
    throw 0;  // <--- never happens
}

int main ()
{
  char a[10];  fun(a);  // ok
  char b[11];  fun(b);  // why works ?
}

为什么fun()接受不同大小的数组值? char[10]char[11]的类型不同吗?

编辑:对于那些说它衰减指针的人,请参阅我编辑过的代码。 char[10]char*似乎不匹配。

8 个答案:

答案 0 :(得分:21)

在这两种情况下,数组衰减到指针类型,而你的函数实际上

void fun (char *a); 

这就是它工作的原因。

我想强调void fun(char*)void fun(char[10])完全相同。 10完全没有任何区别。事实上,10是如此不重要和无用,你甚至可以完全省略它:

void fun (char a[]); //exactly same as `char*` or `char[10]`.

这意味着,所有以下函数声明完全相同:

void fun(char a[10]);   
void fun(char a[]);  //10 is unimportant in the above declaration
void fun(char *a);   //same as above two declarations!

希望澄清你的疑问。


但是,如果你这样写:

void fun (Char10 & a) ; //note &

然后,它实际上是这样的:

void fun (char (&a)[10]) ; //equivalent!

然后fun(b)将无法编译,因为现在fun将仅接受大小为10的数组。并且数组将衰减为指针,它将通过引用传递。

char a[10], b[11];
char *c=new char[10];
fun(a); //okay
fun(b); //error - type mismatch due to size of the array
fun(c); //error - type mismatch due to c being pointer.

答案 1 :(得分:9)

他们是不同的类型,你是对的。

这是一个误导性的C ++怪癖,你可以看到它有一个功能

void fun(char a[10])

由于你不能按值传递数组,而且C ++很傻,这实际上是 函数

void fun(char* a)

当然,两个输入都很快地降级为char*

如果C ++不让你假装按值接受一个数组会很好,但这样做很傻。继承自C。

答案 2 :(得分:4)

Char10char*确实是不同的类型..

尝试

if(typeid(a) == typeid(char*))
    throw 0;  // happens

Online demo

P.S:

以下声明是等效的

void fun(Char10 a);
void fun(char a[]);
void fun(char *a);

答案 3 :(得分:2)

当您收到数组参数时,编译器会将其理解为指向数组第一个元素的指针。运行时,不同大小的数组之间没有区别。这就是为什么你需要知道你正在使用的大小,以避免访问不属于你的程序的内存..

答案 4 :(得分:2)

对于您的编辑:类型本身是不同的,但在C ++中,您不能通过值将数组作为参数传递给函数,并且当您使用数组类型时会衰减为相应的指针类型将它用作函数参数。

#include <iostream>
#include <typeinfo>

using namespace std;

typedef char Char10[10];
void fun (Char10 a) // <-- actually Char10 here is read as char *
{
    Char10 test;
    cout<<(typeid(Char10) == typeid(char*))<<'\n'
        <<(typeid(Char10) == typeid(test))<<'\n'
        <<(typeid(char *) == typeid(a))<<endl;
}

int main ()
{
  char b[11];  fun(b);  // why works ?
}

此输出

0
1
1

由于

  • char *char[10]是不同的类型;
  • testchar[10]
  • a实际上是char *,因为在函数声明中,数组声明会衰减到相应的指针声明。

这是一个愚蠢的事情,这是出于历史原因,但我们坚持下去。


在标准中找到:§8.3.5¶3:

  

在确定每个参数的类型后,将“T数组”或“函数返回T”的任何参数调整为“指向T”或“指针”分别用于返回T,“

答案 5 :(得分:1)

但是,您可以接受对正确大小的数组的引用,此时编译器对其进行反对。

答案 6 :(得分:1)

您既不能在C中也不能在C ++中按值传递数组。 C / C ++中的数组是不可复制的,因此无论你做什么,你都不会用数组类型实现“按值传递”语义。

看起来您希望将数组类型隐藏在typedef-name后面可以让您解决此限制。它不会。你的

void fun(Char10 a)

声明等同于

void fun(char a[10])

声明,相当于

void fun(char a[])

void fun(char *a)

因此,您的a参数具有指针类型。当您传递类似

的数组时
char a[10]; fun(a); 

您只是将char *指针传递给数组的第一个元素。数组的大小无关紧要,这就是为什么你能够使用这种方法传递不同大小的数组。

fun函数中,如果要分析参数a的类型,则应该typeid应用于a

if(typeid(a) == typeid(char*))
  throw 0;

这将显示类型匹配。为什么您将typeid直接应用于Char10以及您希望从中获得的内容对我来说并不清楚。数组类型在函数参数声明中衰减为指针类型,但它们不会衰减到typed运算符中的指针类型,这意味着您的if版本与参数声明中发生的内容完全无关。

答案 7 :(得分:1)

struct char10 {
    char c[10];
};

int foo(char10 param){
...

您可以按这样的值模拟传递固定大小的数组。