Solved

Alternative for sizeof() operator

Posted on 2002-04-23
28
649 Views
Last Modified: 2008-02-01
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
Comment
Question by:prashant_n_mhatre
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
  • 6
  • +5
28 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 6963369
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
 
LVL 86

Expert Comment

by:jkr
ID: 6963376
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
 
LVL 86

Expert Comment

by:jkr
ID: 6963394
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 4

Expert Comment

by:pagladasu
ID: 6963744
jkr, shouldn't p2 be pointing to &a[1] instead of &a[0].
0
 
LVL 86

Accepted Solution

by:
jkr earned 50 total points
ID: 6963758
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
 
LVL 86

Expert Comment

by:jkr
ID: 6963762
Oh, and I forgot to mention how to use template functions also:

size_t sz = alternative_sizeof<int>();
0
 
LVL 30

Expert Comment

by:Axter
ID: 6963792
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
 
LVL 6

Expert Comment

by:thienpnguyen
ID: 6963807
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
 
LVL 6

Expert Comment

by:thienpnguyen
ID: 6963816
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
 
LVL 30

Expert Comment

by:Axter
ID: 6963853
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
 
LVL 6

Expert Comment

by:thienpnguyen
ID: 6963876
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
 
LVL 30

Expert Comment

by:Axter
ID: 6963896
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
 
LVL 30

Expert Comment

by:Axter
ID: 6963903
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
 
LVL 30

Expert Comment

by:Axter
ID: 6963909
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
 
LVL 30

Expert Comment

by:Axter
ID: 6963914
Correction.
If you put a dummy input variable
0
 
LVL 6

Expert Comment

by:thienpnguyen
ID: 6963925
Thank Alex .
0
 
LVL 86

Expert Comment

by:jkr
ID: 6963938
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
 
LVL 30

Expert Comment

by:Axter
ID: 6964098
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
 
LVL 12

Expert Comment

by:pjknibbs
ID: 6964898
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 6964941
#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
 
LVL 49

Expert Comment

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

-- Dan
0
 
LVL 6

Expert Comment

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

0
 
LVL 6

Expert Comment

by:snoegler
ID: 6965112
template<typename T>
size_t alt_sizeof(const T& t)
{
    return ((unsigned char*)((&t)+1))-((unsigned char *)(&t));
}
0
 
LVL 6

Expert Comment

by:snoegler
ID: 6965114
Usage:

alt_sizeof<int>()

or

long double a;
alt_sizeof(a);
0
 
LVL 6

Expert Comment

by:snoegler
ID: 6965126
'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
 
LVL 6

Expert Comment

by:snoegler
ID: 6965692
BTW: My last comment referred to Axters' posting from 04/23/2002 02:36PM PST.
0
 
LVL 6

Expert Comment

by:snoegler
ID: 6970748
Is this thread still alive?
0
 
LVL 4

Author Comment

by:prashant_n_mhatre
ID: 6971819
Thank you all !!!
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question