sizeof()

Pages: 12
Hi, I was confused with the "sizeof()" function. In the main(), why calling the function getSizeof(list1) will return 4; while calling sizeof(list1) return 72.

I want(thought) that getSizeof(list1) should return 72 as well.

Thank you for any comment. Following is my code.

--------------------------------------------------
#include <iostream>
#include <string>
using namespace std;


int getSizeOf(double []);

int main()
{
double list1[]={5,789,34,2,24,22,111,4552,156};

cout<<getSizeOf(list1)<<" "<< sizeof(list1);

return 0;
}



int getSizeOf(double arr[]){

int tempo=sizeof(arr);

return tempo;
}
--------------------------------------------------
In the case of the sizeof(list1) call, the size of list1 is known at compile-time, so sizeof() returns the byte-size of the array. In the getSizeOf() function, the size of "arr" isn't known at compile-time, so sizeof() returns the size of a pointer to double, which is 4 bytes.
sizeof is a keyword, not a function.

sizeof works, in your case, by looking at the type of the variable you are trying to take the size of.

In main(), the compiler is smart enough to realize that list1 is an array of 9 doubles, since the compiler
sees the declaration of list1. Therefore 9 * sizeof double = 72.

In getSizeOf(), the compiler sees that arr is an array of doubles, but it does not know how many doubles
are in the array, since you did not specify. The compiler therefore reverts to treating the array arr as a
pointer, or in other words, it considers arr to be a double*. The size of a pointer-to-double is 4 on a 32
bit platform.
Thank you for both of your speedy replies.

Then, how can i make the getSizeOf() function to know the array size at run-time?

I want to have a function returning the number of elements(or bytes) in an array, without having to count it manually(for example).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
template <typename T,unsigned S>
unsigned ArraySize(const T (&v)[S])  // I hope i did this right ... can't compile to test right now
{
  return S;
}

int main()
{
  double foo[] = {1,2,3,4,5,6};

  cout << ArraySize(foo);  // prints '6'

  // but note that only works with array names, not dynamically allocated arrays

  int* bar = new int[10];
  cout << ArraySize(bar);  // ERROR, 'bar' is not an array name
}

void function(int[] arr)
{
  // it also doesn't work if you pass the array to a function by pointer, because then it
  //becomes a pointer:
  cout << ArraySize(arr);  // ERROR, 'arr' is a pointer, not an array name
}
sizeof is a keyword, not a function.

@ jssmith
i have respect for your knowledge but please prove that sizeof() is NOT a function
Just for the reminder. Despite of acting like a function, it is still a keyword according to the manual.
Also it does not count a reserved memory but reads its predefined substitute text.
@buffbill:

Compile this:

1
2
3
4
5
6
#include <iostream>

int main() {
    int x = sizeof x;   // wouldn't compile if sizeof where a function, right?
    std::cout << x << std::endl;
}


(Or just google it.)
hello chipmunck,

why would you replace sizeof with getSizeOf? I mean when it does the same thing?

This will do the job
1
2
3
4
5
template<class TArrayType>
int getSizeOf(const TArrayType &arr)
{
  return sizeof(arr);
}


This is

...but don't you want the number of elements? like the following

1
2
3
4
5
template<class TArrayType>
int numof(const TArrayType &arr)
{
  return (sizeof(arr) / sizeof(arr[0]));
}

The problem he's having is one I had before, too. In main, list1 is of type int[9]. When he passes it to the function, it's, however, read as int*. The former returns the size of an int, times 9. The latter will return the size of an int, since it doesn't know the amount of integers the array contains.
ahem

I already posted the solution. =P

Here it is again:

1
2
3
4
5
template <typename T,unsigned S>
unsigned ArraySize(const T (&v)[S])
{
  return S;
}


but coder's solution works too.
Last edited on
yes Disch, but um well it looks somewhat ... I don't want to say weird

@ Kyon: don't know what you mean. but what i posted really works (and I use it freqently)
Either will work, given that you pass it as int[9], not int*.
coder777 wrote:
but what i posted really work


What you posted is susceptible to misuse, though, whereas mine is typesafe. For example:

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
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <vector>

using namespace std;

// my "ArraySize" approach
template <typename T,unsigned S>
unsigned ArraySize(const T (&v)[S])
{
  return S;
}

// coder777's "numof" approach
template<class TArrayType>
int numof(const TArrayType &arr)
{
  return (sizeof(arr) / sizeof(arr[0]));
}

int main()
{
    int foo[10];

    // both work fine for arrays
    cout << numof(foo) << endl;
    cout << ArraySize(foo) << endl;

    // but what about dynamically allocated arrays?
    int* bar = new int[10];
    cout << numof(bar) << endl;  // compiles OK, but prints erroneous output
    cout << ArraySize(bar) << endl;  // generates a compiler error


    // or vectors?
    std::vector<int> baz(10);
    cout << numof(baz) << endl;  // again, erroneous output
    cout << ArraySize(baz) << endl;  // compiler error

    cin.get();
	return 0;
}
Last edited on
@coder777, thanks you, i understand your method.

@Disch or any who understands his code at line 7 and 8, what does it do?


line 7, template <typename T,unsigned S>
why use "typename" instead of "class"?


line 8 unsigned ArraySize(const T (&v)[S])
what does the argument do? I have not seen this kind of argument.

I am no c++ expert. So, please give me some reference for my questions.
To chipmunck: typename and class in template declarations are completely interchangeable;
there is absolutely no difference under any circumstance.

The argument is a const reference to an array of S elements of type T. It's best to leave
off the variable name for the parameter since the function doesn't actually use it; a good
compiler would generate a warning at the highest warning level.

Disch's solution is better than coder's solution because, for example, coder's numof()
solution would compile if, say, I passed in a std::vector<std::string> (or any other object
that supported an operator[]), at which point, in this case, it will yield the constant value
sizeof( std::vector ) / sizeof( std::string ) -- not the value you want under any circumstance.

In fact, Disch's solution is a very standard way to get the compiler to tell you the size
of an array, regardless of whether it looks "weird".
@jssmith
yes..i got cold feet and looked it up and found that sizeof() was an operator!!! ( not a key word). Since I have thought it to be a function for about 10 years and what I know about C++ is very small compared with what I don`t know.....its a bit like cashing in your piggy bank to find it full of washers.
Anyway thanks for sorting me out.
BTW
int x = sizeof x;
shouldn`t the second x be in( ) or are these optional.
rgds.
Last edited on
sizeof() was an operator!!! ( not a key word)
It's both.

And yes, the parentheses are not always necessary. But practically no one knows the precedence rules for sizeof, so it's better to just always leave them. They don't hurt and the make the code easier to read.
well Disch and jssmith, you're right. it Disch's solution might be saver.

my method suffers from the same flaw sizeof does (taking everything). but it's easy to understand. i don't know how many ppl understand Disch's solution. and i for my part wouldn't use what i don't understand.

@buffbill
sizeof is both operator and keyword. and yes those () are optional
The only difference is that it's a two argument-template function, rather than one. He uses the address (with &) and then proceeds with the [S] to tell the compiler the amount of "values" the array holds. It's nothing special, you just need to look at it in small portions, not as a whole to understand it (when you haven't got a fine grip of what templates are, no offence intended).
Pages: 12