Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Alternative for sizeof() operator

Posted on 2002-04-23
28
Medium Priority
?
658 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
  • 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
Technology Partners: 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 200 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

Ask an Anonymous Question!

Don't feel intimidated by what you don't know. Ask your question anonymously. It's easy! Learn more and upgrade.

Question has a verified solution.

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

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

773 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