Click here to Skip to main content
15,880,796 members
Please Sign up or sign in to vote.
5.00/5 (3 votes)
See more:
Is there any way to differentiate a pointer from an array.

C++
void Fun(int* p)
{
    // For these values to be proper p should be array of two
    // But how to check if p is an array or is a pointer ?
    int i = p[0];
    int j = p[1];
}

void main()
{
    int a[2] = {1, 2};
    Fun(a);

    int* b = new int;
    *b = 1;
    Fun(b);
}


There are always better alternatives to do this in a better way.

But I want to know if we can differentiate?
Posted
Comments
Amir Mahfoozi 28-Jan-12 3:40am    
read here : http://stackoverflow.com/questions/1025941/any-way-to-detect-whether-the-pointer-points-to-array
Philippe Mori 28-Jan-12 20:35pm    
Should the size always be 2?

The parameter used in Fun() is always a pointer. Whether it started life as a static or dynamic array is impossible to know at that point. The only way to differentiate is at compile time (as Griff suggests), but in the executable code a pointer is always (and only) a pointer.
 
Share this answer
 
Comments
Lakamraju Raghuram 28-Jan-12 5:25am    
Agreed. (-:
There is no way Fun may know that, unless the caller pass it the information.
The usual approach is (see, for instance GetWindowText[^] function): the caller pass the pointer to the buffer together with the size of the buffer itself.
 
Share this answer
 
Comments
Lakamraju Raghuram 28-Jan-12 5:52am    
Ok. This could be one possible work around - To add another argument to get the size. But again we never know if we got static or dynamic memory.
Right!
My 5 for giving this. Though simple it is clean and solves the problem partially
Andreas Gieriet 28-Jan-12 15:06pm    
Well, static versus dynamic memory is another dimansion of the problem. An array may be static, on the stack or on the heap. On some (embedded) OS, it is easy to detect this by checking the memory address ranges.

Cheers

Andi
Philippe Mori 28-Jan-12 17:44pm    
Using template, it can be fixed. See my solution.
CPallini 28-Jan-12 18:07pm    
Yes, but there is the 'type information must not be lost...' caveat.
Albert Holguin 28-Jan-12 19:57pm    
Agreed, this limits the use of that implementation.
With C++, is is quite easy to detect array on the stack using templates.... But type information must not be lost before being used. If you only want to support arrays, then you can delete the first function that works on pointers (or add a size parameter).

Alternatively, you can uses std::vector<int> instead (and have appropriate overload).

C++
void Fun (int *p)
{
    // p is a pointer
}

template <int N> void Fun(int (&p)[N])
{
    // p is an array
}

int main()
{
    int a[5];
    Fun(a);    // Will call second function

    int *p = a;
    Fun(p);    // Will call first function
}


Generally if the code is complexe, then the template version should call a non-template version with an extra argument to avoid code-bloat and keep the convenience of not having to explicitly specify the size at the caller.

By the way first function should generally be deleted (or an extra size argument added) to avoid silent misuse.
 
Share this answer
 
v4
Comments
Andreas Gieriet 28-Jan-12 17:56pm    
My 5!
Andi
Albert Holguin 28-Jan-12 19:55pm    
Good idea... but the caveat CPallini points out is pretty crucial, means the use will not be consistent across all scenarios available when calling a function, so it can be considered unreliable. (+4)
Philippe Mori 28-Jan-12 20:27pm    
If the function with the pointer is deleted, then it is possible to ensure that the templatized function is always called (or the code do not compile). For sure, you have to modify caller up to the declaration as necessary (and you have to be aware of potential code bloat). Generally having a template function that forward to the function with an extra argument for size will fill the needs.
Philippe Mori 28-Jan-12 20:31pm    
Also if the size is known to always be 2 (for ex. 2D points) but you want to ensure it at compilation time, you can simply have the following prototype: void Fun(int (&p)[2]) { ... }
Lakamraju Raghuram 28-Jan-12 21:14pm    
I am getting compilation errors for template <int n=""> void Fun(int (&) p[N] )

// error C2988: unrecognizable template declaration/definition.
// error C2059: syntax error : ')'.
// error C2143: syntax error : missing ';' before '{'.
// error C2447: '{' : missing function header (old-style formal list?).

I am using VC++ compiler. Am I missing any thing !!!!
Since the name of an array is converted into a pointer to the first element (ie. array == &(array[0])), there is a way, sort of, but it won't always work.
The sizeof operator returns the size of an array in bytes if fed an array name, or the size of a pointer if fed a pointer. So, provided that your array contains a different number of bytes to a pointer in your current system, you can tell that way.

Otherwise, I know of no reliable way to tell, in standard C or C++
 
Share this answer
 
Comments
Lakamraju Raghuram 28-Jan-12 3:46am    
Agreed, but in the above case how to feed the array [to Fun method] as array-name. Any way is there ?
OriginalGriff 28-Jan-12 4:02am    
No - it will be converted to &a[0] automatically to fit the pointer requirement of the function parameter.
Lakamraju Raghuram 28-Jan-12 4:24am    
OK. I know that sizeof(arrayName) concept. I too am convinced that there is no proper way, but want to see I some one thinks any different.

Take My 5 for giving a shot.
CPallini 28-Jan-12 5:28am    
However, the sizeof trick does NOT work inside the Fun body. That is, inside Fun there is no way to differentiate.
OriginalGriff 28-Jan-12 5:44am    
Precisely - as I said: "it will be converted to &a[0] automatically to fit the pointer requirement of the function parameter"
An array variable name differs to a plain pointer in the following sense:
C++
// array is not "int *" but "int * const", i.e. the address is const.
int a[] = {1, 2};
a++; // compiler error


Note: One might be tempted to overload F:
F(int *)
F(int * const) (identical to F(int[]))

Unfortunately, this int * const or int[] both translate to int * if it comes to function overlaod.

Cheers

Andi
 
Share this answer
 
Comments
Philippe Mori 28-Jan-12 17:40pm    
See my solution. It is quite easy to detect array with templates.
Lakamraju Raghuram 29-Jan-12 9:33am    
Yes I find philippe's more elegant.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900