passing typedef (fixed sized) array by value
I am having hard time understanding typedef
pattern for arrays.
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 ?
Edit: For those who says it decays to pointer, see my edited code. char[10]
and char*
doesn't seem to match.
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 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.
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.
They are different types, you're right.
It's a misleading quirk of C++ that you can be seen to have a function
void fun(char a[10])
Since you cannot pass arrays by value, and C++ is silly, this is actually the function
void fun(char* a)
And, of course, both inputs degrade happily to 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.
Char10
and char*
are indeed different types..
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);
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..
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.
#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 *
andchar[10]
are different types;test
is achar[10]
a
is actually achar *
, because in function declarations the array declaration decays to the corresponding pointer declaration.
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:
After determining the type of each parameter, any parameter of type “array of
T
” or “function returningT
” is adjusted to be “pointer toT
” or “pointer to function returningT
,” respectively.
You can, however, accept a reference to an array of the correct size, at which point the compiler will object to it.
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.
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
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.
Inside the fun
function, if you want to analyze the type of parameter a
, you are supposed to apply typeid
to 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.
struct char10 {
char c[10];
};
int foo(char10 param){
...
You can emulate passing fixed-size arrays by value like this.
精彩评论