sizeof in function

Pages: 12
Grey Wolf wrote:
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):

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
typedef int  int5[5];  // an array of 5 ints

//...

void func(int5& v) { }
void func2(int*& p) { }

int main()
{
  int* p = new int[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
  }
}
Last edited on
closed account (z05DSL3A)
Disch,

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.
Grey Wolf wrote:
I have not said anything to the contrary.


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

btw, why this:

1
2
typedef int int5[5];
int5 new_int;


and this:

 
int [5] new_int2;


are different?
Last edited on
Well, for one, one of them is invalid.
i know, that's why i ask why... :) btw, can anyone give me a size_t example (my previous question)?
What do you mean by "a size_t example"??
hmm... i mean example of using it...
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.
Last edited on
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... :)
Last edited on
Types don't return values...

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(const int (&v)[5])
{
  // here, 'v' is an array of 5 ints
}

int main()
{
  int ar5[5];
  int ar6[6];
  int* p = new int[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(const int (&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
}
thanks for your reply man. i guess i'm clear about this. but how about my question above? about typedef and non-typedef
Topic archived. No new replies allowed.
Pages: 12