I believe that sizeof() is the exception to the rule, probably because its behavior is specified in the standard.
On the contrary, sizeof does not do anything out of the ordinary. The reason it treats pointers and arrays differently is because they are subtlely different.
Arrays are their own type, independent from pointers. The thing that blurs the line is that they can be implicitly cast to pointers.
This can be seen any number of ways in programs (many of which have been illustrated in this thread already):
typedefint int5[5]; // an array of 5 ints
//...
void func(int5& v) { }
void func2(int*& p) { }
int main()
{
int* p = newint[5];
int5 v;
p = v; // OK, implicit cast (the source of the confusion)
func(p); // fails. pointers are not arrays
func(v); // OK, arrays are arrays
func2(p); // OK, pointers are pointers
func2(v); // fails, arrays are not pointers
cout << sizeof(p); // prints size of a pointer (p is a pointer)
cout << sizeof(v); // prints size of the array (v is an array)
if(typeid(p) == typeid(v))
{
// fails. p and v are not matching types
}
}
I'm not sure what your point is in reference to what I have said in this thread.
you wrote:
Arrays are their own type, independent from pointers. The thing that blurs the line is that they can be implicitly cast to pointers.
I have not said anything to the contrary.
The only thing that I did not explain at the time, but have since done so in an edit, is why sizeof does not implicitly convert the name to a pointer when used.
You kind of did in the original post I replied to, although now that I read it again you didn't really:
GreyWolf wrote:
When every you use the name of an array in an expression, the name is automatically converted to a pointer to the first element. It does not matter it is a parameter to a function or anywhere else in your code.
At first I thought you meant to say that they were the same, but now reading it, it looks like you're saying they implicitly cast.
yeah, i thought so, but after i read it (carefully), seems like you are trying to say that it's (the array) treated as if it is a pointer. so they're not the same (because you said you didn't said the otherwise ("contrary" in your post). talking about words and perspective, that could be confusing dude... :DD
size_t is just a typedef-ed type used throughout most of the Standard Library. Asking for an example of its use is like saying "could I have an example of how to use an int?", which doesn't make sense.
because what i read about this type is it returns a value of byte and i saw the example of framework in http://cplusplus.com/forum/beginner/45263/#msg245719 (i.e. the page next to this page) i don't know why the sizt_t could determine the size of the character passed to the function. so i want the explanation of using it, how it works... :)
In the example Framework posted, the compiler can deduce the template parameters and automatically adds the <> with the correct parameters. size_t could just as easily be replaced by unsigned long, int, or any other type. It's just a type.
that doesn't have anything to do with size_t, it has to do with a template.
To understand the syntax, here's a simple example of an underlying function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
void func5(constint (&v)[5])
{
// here, 'v' is an array of 5 ints
}
int main()
{
int ar5[5];
int ar6[6];
int* p = newint[5];
func5(ar5); // OK
func5(ar6); // fails, int[6] is not int[5]
func5(p); // fails, int* is not int[5]
}
Now let's say we want to template this function so the array can be of any size, not just of size 5. We can just replace the 5 with a template parameter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
template <unsigned S>
void funcT(constint (&v)[S])
{
// here, 'v' is an array of 'S' ints, where 'S' is the template parameter
}
int main()
{
int ar6[6];
funcT<6>(ar6); // OK
int ar5[5];
funcT<5>(ar5); // OK
}
Above I'm explicitly putting the <6> and <5> to say which values I want for 'S' in the function. However this isn't really necessary because the compiler can figure that out automatically based on the array we're passing. So I can leave out that part:
1 2
int ar6[6];
funcT(ar6); // OK, same as funcT<6>(ar6)
Going one step further, if we want this function to work with any type and not just ints, we can make that a template parameter as well:
1 2 3 4 5 6 7 8 9 10 11 12
template <typename T,unsigned S>
void func(const T (&v)[S])
{
// here, 'v' is an array of size 'S'. Each element in the array is of type 'T'
}
int main()
{
double d5[5];
func<double,5>( d5 ); // OK, T=double S=5
func( d5 ); // OK, same as above. T and S are automatically figured out by the compiler
}
Using this, we can create the classic "arraysize" function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
template<typename T,unsigned S>
unsigned arraysize(const T (&v)[S])
{
return S; // return S (the size of the array)
}
int main()
{
int ar5[5];
cout << arraysize(ar5); // prints 5
double ar10[10];
cout << arraysize(ar10); // prints 10
int foo[] = {1,2,3,4,5,6,7,8,9,10,11,12};
cout << arraysize(foo); // prints 12
}