Reputation: 1241
If I have int x[10]
and int *y
, how can I tell the difference between the two?
I have two ideas:
sizeof() is different.
&x has different type ---
int (*p)[10] = &x
works but notint **q = &x
.
Any others?
In some template library code, I need to determine whether a pointer is a "real" pointer or degenerated from an array. I can't look at source code as the library user does not exist until I write the library. ... I can work around this by rewriting the code, so now this is only a theoretical exercise.
Upvotes: 2
Views: 1023
Reputation: 147
I just tried the equivalent in g++ 4.5 C++0x mode for char arrays and it won't let me both define
template <typename T>void moresilly(const T v[],const char *description)
AND
template <typename T>void moresilly(const T *v,const char *description)
it claims both are the same type.
I had a function:
template <typename T>void silly(const T & v,const char *description)
{
cout<<"size of "<<description<<" is "<< sizeof(T)<<endl;
moresilly(v,description);
}
It correctly gets the size of an array if passed and of a pointer if passed, but I can't use moresilly to distinguish between pointer and array, so I can't tell a 4 character array from pointer to n characters.
It might work, sort of, to have templates on T[1],T[2], T[3] etc. but there's already a post saying that different compilers handle that (or some similar case) differently and that gnu prefers a pointer match in C++11.
... added later: After some experiment I found something that works in g++ 4.5
template <typename T,size_t L>void moresilly(const T (&v)[L],const char *description)
{
cout<<description<<" is an array"<<endl;
}
template <typename T>void moresilly(const T *v,const char *description)
{
cout<<description<<" is a pointer"<<endl;
}
template <typename T>void moresilly(const T v,const char *description)
{
cout<<description<<" is a raw value"<<endl;
}
template <typename T>void silly(const T & v,const char *description)
{
cout<<"size of "<<description<<" is "<< sizeof(T)<<endl;
moresilly(v,description);
}
with the following works properly
silly("12345","immediate string of 5 characters plus zero");
silly((const char *)"12345","immediate constant char pointer of 5 characters plus zero");
char testarray[]="abcdef";
silly(testarray,"char array of 6 characters plus zero");
const char testarray2[]="abcdefg";
silly(testarray2,"const char array of 7 characters plus zero");
Note that if the first function is defined with "const T v[L]" instead of "const T (&v)[L]" it doesn't work, never matching anything.
So I solved your problem but don't expect this to work in other versions of the compiler including future ones. This is why I hate c++. Somehow the definition of the language is so unclear that compilers are full of unstable edge cases.
This is a useful trick though, I may use it.
Upvotes: 0
Reputation: 54594
Assuming that you aren't trying to do this for a type declared at function scope:
struct yes { char pad; };
struct no { yes pad[2]; };
template <typename T, size_t N> yes is_array_test(T (&arr)[N]);
no is_array_test(...);
#define IS_ARRAY(x) (sizeof(is_array_test(x))==sizeof(yes))
Upvotes: 2
Reputation: 1726
They are different types.
How do you tell the difference between an int32 and a uint32, or a uint32 and a char[4]?
The right way to think of it is that the only way that they are similar is that in certain contexts (including array indexing!) an array promotes into a pointer.
Upvotes: 0
Reputation: 12140
int x[10] will be allways allocated on the stack at the place were it is called. x value can never be changed.
int *y simply declare a pointer to a memory , the pointer value can be changed at any time without any restrictions.
int *y can have any arbitrary value. Meaning , it can point to stack-allocated Memoryor heap allocated memory. Technicly it can also point to invalid memory but that won't make any sense.
int x[10] guarntee you are allways pointing to a valid memory and you don't have to worry about memory deallocation.
when using int* y , you have to worry about the memory it is pointing to .
Also keep in mind that the lot your porgram has dynamically allocated memory the more it will be exposed to errors , leaks , performece issues , allocation\deallocation assimetry and many other kinds of problem.
Upvotes: 0
Reputation: 116674
The sizeof
idea is not very good, because if the array happens to have a single element, and the element type happens to be the same size as a pointer, then it will be the same size as the size of a pointer.
The type matching approach looks more promising, and could presumably be used to pick a template specialization (if that's what you're up to).
Upvotes: 2
Reputation:
There is no general method - you either already know the type because you have just declared the object, or the type will have decayed to a pointer and been lost. Please explain what problem you are trying to solve by differentiating between them.
Upvotes: 5