This is one of those things that is hard to understand in C and C++ just because people have to be so pedantic about this stuff. (With good reason.)
From what you are trying to understand, then yes, it is a const pointer.
Except that an array is not a pointer, which is the point
cire is making.
When compiling, the compiler understands
int a[12]
to have a named value called 'a' which consists of the following information:
- address of the first element in the array (a const pointer!)
- type of elements in the array
- length of the array
In contrast, a pointer
int* p
only has the following information associated with it:
- address of the element it addresses (a pointer)
- type of the element it addresses
These two things are pretty darn close. In code generated to access stuff, it is exactly the same:
a[2] is semantically equivalent to
*(p + 2)
What muddles it is that an array address is a pointer, so using an array's name (its identifier) in a pointer context causes it to degenerate into a pointer. This happens when passing to a function, for example:
1 2 3 4 5 6 7 8 9 10 11 12
|
void print( int* p )
{
cout << *p << endl;
}
int main()
{
int a[ 5 ] = { 2, 3, 5, 7, 11 };
print( a );
print( a + 3 );
}
|
2
7 |
It is the same reason that you must pass the length of an array to a function:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
void print( int* p, unsigned size )
{
for (unsigned n = 0; n < size; n++)
cout << p[ n ] << " ";
cout << "\b\n";
}
int main()
{
int a[ 5 ] = { 2, 3, 5, 7, 11 };
print( a, 5 );
}
|
2 3 5 7 11 |
You can make life easier with a template function helper:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
template <unsigned N>
inline
void print( int (&a)[ N ] )
{
print( a, N );
}
int main()
{
int a[ 5 ] = { 2, 3, 5, 7, 11 };
print( a );
}
|
2 3 5 7 11 |
The reason the helper works, of course, is that 'a' is an array, which knows its size. So when you call
print( a )
, the function helper gets called instead of any pointer function.
If you want to use them together, though, you have to help the compiler, since the array will degenerate into a pointer at the earliest convenience. So make sure you use
references for everything to force the compiler to choose the correct item.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
#include <iostream>
using namespace std;
void print( int*& p )
{
cout << *p << endl;
}
void print( int* p, unsigned size )
{
for (unsigned n = 0; n < size; n++)
cout << p[ n ] << " ";
cout << "\b\n";
}
template <size_t N>
inline
void print( int (&a)[ N ] )
{
print( a, N );
}
int main()
{
int a[ 5 ] = { 2, 3, 5, 7, 11 };
print( a );
int* p = a;
print( p );
}
|
2 3 5 7 11
2 |
It's enough to make your head swim, no?