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
prashant_n_mhatreAsked:
Who is Participating?
 
jkrCommented:
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
 
jkrCommented:
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
 
jkrCommented:
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
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

 
jkrCommented:
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
 
pagladasuCommented:
jkr, shouldn't p2 be pointing to &a[1] instead of &a[0].
0
 
jkrCommented:
Oh, and I forgot to mention how to use template functions also:

size_t sz = alternative_sizeof<int>();
0
 
AxterCommented:
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
 
thienpnguyenCommented:
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
 
thienpnguyenCommented:
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
 
AxterCommented:
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
 
thienpnguyenCommented:
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
 
AxterCommented:
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
 
AxterCommented:
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
 
AxterCommented:
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
 
AxterCommented:
Correction.
If you put a dummy input variable
0
 
thienpnguyenCommented:
Thank Alex .
0
 
jkrCommented:
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
 
AxterCommented:
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
 
pjknibbsCommented:
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
 
DanRollinsCommented:
#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
 
DanRollinsCommented:
pknibbs,
Since the two variables are adjadent members of a two-element array, I think that technique is safe.

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

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

alt_sizeof<int>()

or

long double a;
alt_sizeof(a);
0
 
snoeglerCommented:
'A_Type1' : const object must be initialized if not extern

Your line

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
 
snoeglerCommented:
BTW: My last comment referred to Axters' posting from 04/23/2002 02:36PM PST.
0
 
snoeglerCommented:
Is this thread still alive?
0
 
prashant_n_mhatreAuthor 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.

All Courses

From novice to tech pro — start learning today.