You have two different types:
int x[10];
This declares a type of int[10]
. As you can see, the size of the array is part of the type.
int * y;
This is a pointer to an int. It will have size equivalent to the size of a pointer on your system. Your system appears to have 64 bit pointers (commonplace now).
Here's a little trick you can do in C++17:
template<class T>
std::enable_if_t<std::is_pointer_v<T>> foo(T ptr)
{
std::cout << "Called foo for a pointer type" << std::endl;
}
template<class T, int N>
void foo(T (&arr)[N])
{
std::cout << "Called foo for an array type of size " << N << std::endl;
}
We defined two functions named foo
. The first one uses type traits to only enable itself for pointer types, and the second one is for array types (by reference).
We can call them from main:
int x[10];
int * y = nullptr;
foo(x);
foo(y);
And get output that looks like this:
Called foo for an array type of size 10
Called foo for a pointer type
Edit: Mark Ransom gave a good aside about the size of the array allocated for y
, and I'll throw in a little piece, too. While it is indeed an implementation detail, what's common is that the implementation of the memory allocator (like malloc
or new
) under the hood will write this value to the start of the memory block that it allocates.
That way, when you call delete
, you don't have to know how many bytes to delete; the deallocator (free
or delete
) can check the start of the memory block for how big it is. So an allocation for, say 1 byte, may actually allocate more than 1 byte. (Again, this is only one way it can be done)