# Alternative for sizeof() operator

This question was asked by someone in interview.
How to find the size of a variable without using
sizeof() operator?

I'd thought of using <limits.h> and to decide size using
MAX_INT etc..

Don't know if I'm correct...Any ideas?
LVL 4
###### Who is Participating?

Commented:
Yes, thanks, you're absolutely right :o)

So, it is

typedef unsigned char BYTE;

VARTYPE a [ 2];

BYTE* p1 = ( BYTE*) &a [ 0];
BYTE* p2 = ( BYTE*) &a [ 1];

int sizeof_vartype = p2 - p1;

and/or

typedef unsigned char BYTE;

template <class T>
size_t
alternative_sizeof () {

T a[ 2];

BYTE* p1 = ( BYTE*) &a [ 0];
BYTE* p2 = ( BYTE*) &a [ 1];

return p2 - p1;
}
0

Commented:
Use the following to calc the "memory size" of a variable:

VARTYPE a [ 2];

BYTE* p1 = ( BYTE*) &a [ 0];
BYTE* p2 = ( BYTE*) &a [ 0];

int sizeof_vartype = p2 - p1;
0

Commented:
Or, to do it the C++ way:

size_t
template<class T>
alternative_sizeof () {

T a[ 2];

BYTE* p1 = ( BYTE*) &a [ 0];
BYTE* p2 = ( BYTE*) &a [ 0];

return p2 - p1;
}
0

Commented:
Ooops, a little correction to the template func - it should read

typedef unsigned char BYTE;

template <class T>
size_t
alternative_sizeof () {

T a[ 2];

BYTE* p1 = ( BYTE*) &a [ 0];
BYTE* p2 = ( BYTE*) &a [ 0];

return p2 - p1;
}
0

Commented:
jkr, shouldn't p2 be pointing to &a[1] instead of &a[0].
0

Commented:
Oh, and I forgot to mention how to use template functions also:

size_t sz = alternative_sizeof<int>();
0

Commented:
jkr,
That's pretty neat.

Just to add to jkr's method you could modify it to the following, and make it easier to pass a specific variable.

template <class T>
size_t alternative_sizeof (const T& Src)
{
T a[ 2];

char* p1 = ( char*) &a [ 0];
char* p2 = ( char*) &a [ 1];

return p2 - p1;
}

Example code:
int main(int, char*)
{
int foo[3];
char data[33];
long foofoo;
size_t x1 = alternative_sizeof(foo);
size_t x2 = alternative_sizeof(data);
size_t x3 = alternative_sizeof(foofoo);

cout << x1 << endl;
cout << x2 << endl;
cout << x3 << endl;

system("pause");
return 0;
}
0

Commented:
jkr,

Only friendly remind, you have a little bit typo

// BYTE* p2 = ( BYTE*) &a [ 0];
BYTE* p2 = ( BYTE*) &a [1];

I agree with your comment . However, when I run a test program on VC++ 6 , I don't have the expect result . Is it a VC++ 6 's bug ?

Based on your comment, I suggest to change code as following

template <class T>
size_t  mysizeof( T *p = NULL)
{
// don't need to call constructors for T a[ 2];

return (BYTE *) (p+1) - (BYTE *) p;
}

--------------------------------

The demo code

#include <windows.h>
#include <iostream>
using namespace std;

class Foo
{
public:
int i[100];
char *p;
};

template <class T>
size_t
alternative_sizeof ()
{

T a[ 2];

BYTE* p1 = ( BYTE*) &a [ 0];
BYTE* p2 = ( BYTE*) &a [ 1];

return p2 - p1;
}

template <class T>
size_t  mysizeof( T *p = NULL) {

return (BYTE *) (p+1) - (BYTE *) p;
}

void main()
{
int   i = 1;
char  c;
Foo   foo;

cout << " alternative_sizeof int  = "  << alternative_sizeof<int>()   << endl;
cout << " alternative_sizeof char = "  << alternative_sizeof<char>() << endl;
cout << " alternative_sizeof Foo  = "  << alternative_sizeof<Foo>()   << endl << endl;

cout << " mysizeof int  = "  << mysizeof<int>()   << endl;
cout << " mysizeof char = "  << mysizeof<char>() << endl;
cout << " mysizeof Foo  = "  << mysizeof<Foo>()   << endl;

}
The result :

#include <windows.h>
#include <iostream>
using namespace std;

class Foo
{
public:
int i[100];
char *p;
};

template <class T>
size_t
alternative_sizeof ()
{

T a[ 2];

BYTE* p1 = ( BYTE*) &a [ 0];
BYTE* p2 = ( BYTE*) &a [ 1];

return p2 - p1;
}

template <class T>
size_t  mysizeof( T *p = NULL) {

return (BYTE *) (p+1) - (BYTE *) p;
}

void main()
{
int   i = 1;
char  c;
Foo   foo;

cout << " alternative_sizeof int  = "  << alternative_sizeof<int>()   << endl;
cout << " alternative_sizeof char = "  << alternative_sizeof<char>() << endl;
cout << " alternative_sizeof Foo  = "  << alternative_sizeof<Foo>()   << endl << endl;

cout << " mysizeof int  = "  << mysizeof<int>()   << endl;
cout << " mysizeof char = "  << mysizeof<char>() << endl;
cout << " mysizeof Foo  = "  << mysizeof<Foo>()   << endl;

}

0

Commented:
The result is

alternative_sizeof int  = 404        ???
alternative_sizeof char = 404        ???
alternative_sizeof Foo  = 404

mysizeof int  = 4
mysizeof char = 1
mysizeof Foo  = 404
0

Commented:
thienpnguyen,
I tested it out, and I didn't get the above results.
jkr's method gives the same results as your method.
You must have a type-O in your code some where.
0

Commented:
Alex,

Thank for reply. But I want to make sure , you test with jkr code or your code .  Your function has a argument and it is ok . [ but Jkr's fucntion doesn't have any argument ]

I know, the jkr's code is correct in theory . However, I don't know why it has bug in VC++ 6.0 ?

Note : if you have time, could you run my code ? I only want to know on your compiler,  the bug happends or not . Thank for reading .
0

Commented:
thienpnguyen,
Actually, after testing jkr's method, and your method, plus mind, I find your right.
Although, I still don't get the same results as you get.
Here's the test code.

template <class T>
size_t alternative_sizeof_jkrs_method_plus_axter(const T&)
{
T a[2];
return (char*) &a[1] - (char*) &a[0];
}

template <class T>
size_t alternative_sizeof_jkrs_method()
{
T a[2];
char* p1 = ( char*) &a [ 0];
char* p2 = ( char*) &a [ 1];
return p2 - p1;
}

template <class T>
size_t  alternative_sizeof_thienpnguyen_method( T *p = NULL) {

return (char *) (p+1) - (char *) p;
}

class Foo
{
public:
int i[100];
char *p;
};

int main(int, char*)
{
int int_3[3];
char char_33[33];
long long_type;
Foo SomeFoo;
cout << endl  << "alternative_sizeof_jkrs_method" << endl;
cout << alternative_sizeof_jkrs_method<int>() << endl;
cout << alternative_sizeof_jkrs_method<Foo>() << endl;
cout << alternative_sizeof_jkrs_method<char>() << endl;

cout << endl  << "alternative_sizeof_jkrs_method_plus_axter" << endl;
cout << alternative_sizeof_jkrs_method_plus_axter(int_3) << endl;
cout << alternative_sizeof_jkrs_method_plus_axter(char_33) << endl;
cout << alternative_sizeof_jkrs_method_plus_axter(long_type) << endl;
cout << alternative_sizeof_jkrs_method_plus_axter(SomeFoo) << endl;

cout << endl  << "alternative_sizeof_thienpnguyen_method" << endl;
cout << alternative_sizeof_thienpnguyen_method(&int_3) << endl;
cout << alternative_sizeof_thienpnguyen_method(&char_33) << endl;
cout << alternative_sizeof_thienpnguyen_method(&long_type) << endl;
cout << alternative_sizeof_thienpnguyen_method<int>() << endl;
cout << alternative_sizeof_thienpnguyen_method<Foo>() << endl;
cout << alternative_sizeof_thienpnguyen_method(&SomeFoo) << endl;
cout << alternative_sizeof_thienpnguyen_method<char>() << endl;

system("pause");
return 0;
}
0

Commented:
I get the following results from above code:

alternative_sizeof_jkrs_method
1
1
1

alternative_sizeof_jkrs_method_plus_axter
12
33
4
404

alternative_sizeof_thienpnguyen_method
12
33
4
4
404
404
1

Not what I expected!!!
0

Commented:
If you put a dummy variable in jkr's method, it works.

template <class T>
size_t alternative_sizeof_jkrs_method(T *p = NULL)
{
T a[2];
char* p1 = ( char*) &a [ 0];
char* p2 = ( char*) &a [ 1];
return p2 - p1;
}
0

Commented:
Correction.
If you put a dummy input variable
0

Commented:
Thank Alex .
0

Commented:
Yikes, this looks like a compiler bug:

void main () {

cout << alternative_sizeof<int>() << endl;

}

works, whereas

void main () {

cout << alternative_sizeof<int>() << endl;
cout << alternative_sizeof<char>() << endl;
}

produces incorrect results...
0

Commented:
What's also strange is that even when I use jkr's method to call the method that accepts a variable, it still comes out wrong.
Example:
template <class T>
size_t alternative_sizeof(const T&)
{
T a[2];
return (char*) &a[1] - (char*) &a[0];
}

template <class T>
size_t alternative_sizeof()
{
T A_Type1;
return alternative_sizeof(A_Type1);
}

And if I modify it to a const, then VC fails to compile it.
Example:
template <class T>
size_t alternative_sizeof()
{
const T A_Type1;
return alternative_sizeof(A_Type1);
}
This produces the following error:
************************************
'A_Type1' : const object must be initialized if not extern
************************************

I don't know what that's all about.
0

Commented:
Isn't there a slight problem with this subtracting pointer method to find the size of a variable? It's implicitly assuming that the compiler allocates the two variables in memory next to each other, and I don't think this is in any way guaranteed in the C++ specification.
0

Commented:
#include <stddef.h>
typedef struct {
int n;
char locator;
} TestRec;

int nMySizeOfInt= offsetof( TestRec, locator );

This macro is kind of interesting:

#define offsetof(s,m)   (size_t)&(((s *)0)->m)

It coerces 0 into a pointer to a structure and then gets the address of the member.

A real expert could probably make a template out of it!  Wouldn't that be fun!

-- Dan
0

Commented:
pknibbs,
Since the two variables are adjadent members of a two-element array, I think that technique is safe.

-- Dan
0

Commented:
template<typename T>
size_t alt_sizeof()
{
return ((unsigned char*)((((T*)0)+1))-((unsigned char *)((T*)0)));
}

0

Commented:
template<typename T>
size_t alt_sizeof(const T& t)
{
return ((unsigned char*)((&t)+1))-((unsigned char *)(&t));
}
0

Commented:
Usage:

alt_sizeof<int>()

or

long double a;
alt_sizeof(a);
0

Commented:
'A_Type1' : const object must be initialized if not extern

const T A_Type1;

translates to (for example)

const int BLA;

Now the compiler wonders why you define a const variable w/o assigning a value to it. Since it is 'const', you may not (though you can) modify its value later. Hence the error.
0

Commented:
BTW: My last comment referred to Axters' posting from 04/23/2002 02:36PM PST.
0

Commented:
0

Author Commented:
Thank you all !!!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.