[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 664
  • Last Modified:

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?
0
prashant_n_mhatre
Asked:
prashant_n_mhatre
  • 7
  • 6
  • 6
  • +5
1 Solution
 
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
 
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
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
pagladasuCommented:
jkr, shouldn't p2 be pointing to &a[1] instead of &a[0].
0
 
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:
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

Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

  • 7
  • 6
  • 6
  • +5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now