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

时间:2022-09-26 21:31:42

I am having hard time understanding typedef pattern for arrays.

我很难理解数组的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 ?
}

Why the different sizes of array by value are accepted by fun() ? Are char[10] and char[11] not different types ?

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

Edit: For those who says it decays to pointer, see my edited code. char[10] and char* doesn't seem to match.

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

8 个解决方案

#1


9  

They are different types, you're right.

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

It's a misleading quirk of C++ that you can be seen to have a function

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

void fun(char a[10])

Since you cannot pass arrays by value, and C++ is silly, this is actually the function

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

void fun(char* a)

And, of course, both inputs degrade happily to char*.

当然,两个输入都很快地降低到char *。

It would be nice if C++ did not let you even pretend to accept an array by value, but it is silly in this way.. inherited from C.

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

#2


21  

In both cases, the arrays decay to the pointer type, and your function is actually this:

在这两种情况下,数组都会衰减为指针类型,而您的函数实际上是这样的:

void fun (char *a); 

That is why its working.

这就是它工作的原因。

I would like to emphasize that void fun(char*) is exactly same as void fun(char[10]). The 10 doesn't make any difference at all. In fact, 10 is so unimportant and useless that you can even omit it completely as:

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

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

That means, all the following function declarations are exactly same:

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

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!

Hope that clarifies your doubt.

希望澄清你的疑问。


However, if you write this:

但是,如果你这样写:

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

then, its actually this:

那么,它实际上是这样的:

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

Then fun(b) wouldn't compile, as now fun will accept ONLY array of EXACTLY size 10. And the array will not decay to pointer, it will be passed by reference.

然后有趣(b)将无法编译,因为现在乐趣将接受仅有大小为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.

#3


4  

Char10 and char* are indeed different types..

Char10和char *确实是不同的类型..

Try

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

Online demo

P.S:

The following declarations are equivalent

以下声明是等效的

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

#4


2  

When you receive an array parameter, the compiler understands it as a pointer to the array's first element. There's no difference between arrays of different sizes at runtime. That's why you need to know the size you are working with to avoid accessing memory that does not belong to your program..

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

#5


2  

For your edit: the types per se are different, but in C++ you cannot pass an array by value as an argument to a function, and the array type decays to the corresponding pointer type when you use it as a function argument.

对于您的编辑:类型本身是不同的,但在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 ?
}

This outputs

0
1
1

Because

  • char * and char[10] are different types;
  • char *和char [10]是不同的类型;

  • test is a char[10]
  • 测试是一个char [10]

  • a is actually a char *, because in function declarations the array declaration decays to the corresponding pointer declaration.
  • a实际上是一个char *,因为在函数声明中,数组声明衰减到相应的指针声明。

This is a stupid thing that is here for historical reasons, but we're stuck with it.

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


Found in the standard: at §8.3.5 ¶3:

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

After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively.

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

#6


1  

You can, however, accept a reference to an array of the correct size, at which point the compiler will object to it.

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

#7


1  

You cannot pass array by value neither in C nor in C++. Arrays in C/C++ are non copyable, so regardless of what you do, you will never achieve "pass by value" semantics with array type.

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

It looks like you hoped that hiding the array type behind a typedef-name will let you work around this limitation. It won't. Your

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

void fun(Char10 a)

declaration is equivalent to

声明相当于

void fun(char a[10])

declaration, which is in turn equivalent to

声明,相当于

void fun(char a[])

and to

void fun(char *a)

So, your a parameter has pointer type. When you pass an array like that

所以,你的参数有指针类型。当你传递这样的数组时

char a[10]; fun(a); 

you are simply passing a char * pointer to the first element of the array. The size of the array does not matter, which is why you are able to pass arrays of different sizes using this method.

您只是将char *指针传递给数组的第一个元素。数组的大小无关紧要,这就是您可以使用此方法传递不同大小的数组的原因。

Inside the fun function, if you want to analyze the type of parameter a, you are supposed to apply typeid to a

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

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

This will show you that the types match. Why you are applying the typeid directly to Char10 and what you are expecting to derive from it is not clear to me. Array types decay to pointer types in function parameter declaration, but they don't decay to pointer types in typed operator, meaning that your version of if is absolutely unrelated to what happens in parameter declaration.

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

#8


1  

struct char10 {
    char c[10];
};

int foo(char10 param){
...

You can emulate passing fixed-size arrays by value like this.

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

#1


9  

They are different types, you're right.

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

It's a misleading quirk of C++ that you can be seen to have a function

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

void fun(char a[10])

Since you cannot pass arrays by value, and C++ is silly, this is actually the function

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

void fun(char* a)

And, of course, both inputs degrade happily to char*.

当然,两个输入都很快地降低到char *。

It would be nice if C++ did not let you even pretend to accept an array by value, but it is silly in this way.. inherited from C.

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

#2


21  

In both cases, the arrays decay to the pointer type, and your function is actually this:

在这两种情况下,数组都会衰减为指针类型,而您的函数实际上是这样的:

void fun (char *a); 

That is why its working.

这就是它工作的原因。

I would like to emphasize that void fun(char*) is exactly same as void fun(char[10]). The 10 doesn't make any difference at all. In fact, 10 is so unimportant and useless that you can even omit it completely as:

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

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

That means, all the following function declarations are exactly same:

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

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!

Hope that clarifies your doubt.

希望澄清你的疑问。


However, if you write this:

但是,如果你这样写:

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

then, its actually this:

那么,它实际上是这样的:

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

Then fun(b) wouldn't compile, as now fun will accept ONLY array of EXACTLY size 10. And the array will not decay to pointer, it will be passed by reference.

然后有趣(b)将无法编译,因为现在乐趣将接受仅有大小为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.

#3


4  

Char10 and char* are indeed different types..

Char10和char *确实是不同的类型..

Try

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

Online demo

P.S:

The following declarations are equivalent

以下声明是等效的

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

#4


2  

When you receive an array parameter, the compiler understands it as a pointer to the array's first element. There's no difference between arrays of different sizes at runtime. That's why you need to know the size you are working with to avoid accessing memory that does not belong to your program..

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

#5


2  

For your edit: the types per se are different, but in C++ you cannot pass an array by value as an argument to a function, and the array type decays to the corresponding pointer type when you use it as a function argument.

对于您的编辑:类型本身是不同的,但在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 ?
}

This outputs

0
1
1

Because

  • char * and char[10] are different types;
  • char *和char [10]是不同的类型;

  • test is a char[10]
  • 测试是一个char [10]

  • a is actually a char *, because in function declarations the array declaration decays to the corresponding pointer declaration.
  • a实际上是一个char *,因为在函数声明中,数组声明衰减到相应的指针声明。

This is a stupid thing that is here for historical reasons, but we're stuck with it.

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


Found in the standard: at §8.3.5 ¶3:

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

After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively.

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

#6


1  

You can, however, accept a reference to an array of the correct size, at which point the compiler will object to it.

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

#7


1  

You cannot pass array by value neither in C nor in C++. Arrays in C/C++ are non copyable, so regardless of what you do, you will never achieve "pass by value" semantics with array type.

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

It looks like you hoped that hiding the array type behind a typedef-name will let you work around this limitation. It won't. Your

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

void fun(Char10 a)

declaration is equivalent to

声明相当于

void fun(char a[10])

declaration, which is in turn equivalent to

声明,相当于

void fun(char a[])

and to

void fun(char *a)

So, your a parameter has pointer type. When you pass an array like that

所以,你的参数有指针类型。当你传递这样的数组时

char a[10]; fun(a); 

you are simply passing a char * pointer to the first element of the array. The size of the array does not matter, which is why you are able to pass arrays of different sizes using this method.

您只是将char *指针传递给数组的第一个元素。数组的大小无关紧要,这就是您可以使用此方法传递不同大小的数组的原因。

Inside the fun function, if you want to analyze the type of parameter a, you are supposed to apply typeid to a

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

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

This will show you that the types match. Why you are applying the typeid directly to Char10 and what you are expecting to derive from it is not clear to me. Array types decay to pointer types in function parameter declaration, but they don't decay to pointer types in typed operator, meaning that your version of if is absolutely unrelated to what happens in parameter declaration.

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

#8


1  

struct char10 {
    char c[10];
};

int foo(char10 param){
...

You can emulate passing fixed-size arrays by value like this.

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