Solved

Alternative for sizeof() operator

Posted on 2002-04-23
28
642 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
 
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
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
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

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Handling string inputs in C/Linux 23 168
Converting to C# also VS2015 5 110
thread-safe code in c++ 2 72
Path to  STL Map header file 1 29
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

747 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now