开发者

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 * and char[10] are different types;
  • test is a char[10]
  • a is actually a char *, 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 returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜