Implementing the sizeof operator

  • Thread starter Abhishek Srivastava
  • Start date
A

Abhishek Srivastava

Hi,

Somebody recently asked me to implement the sizeof operator, i.e. to
write a function that accepts a parameter of any type, and without
using the sizeof operator, should be able to return the size occupied
by that datatype in memory in bytes. Thanks :)

Abhishek Srivastava
 
A

Alf P. Steinbach

* Abhishek Srivastava:
Somebody recently asked me to implement the sizeof operator, i.e. to
write a function that accepts a parameter of any type, and without
using the sizeof operator, should be able to return the size occupied
by that datatype in memory in bytes. Thanks :)

This sounds like HOMEWORK.

One must hope that nobody provides source code for you (although they
invariably do, to show off their ability to code trivial things).

Hint: array.
 
T

Tom Widmer

Abhishek said:
Hi,

Somebody recently asked me to implement the sizeof operator, i.e. to
write a function that accepts a parameter of any type, and without
using the sizeof operator, should be able to return the size occupied
by that datatype in memory in bytes. Thanks :)

Note that the difference in address between two adjacent elements of an
array is equal to the size of an element.

Tom
 
A

Abhishek Srivastava

Hi Alf P. Steinbach :)

This is not homework. Just wanted to know because I couldn't think of
the solution. Hmmmm.... your hint is to use an array, still pondering
over that. Thanks anyway.
 
F

Frederick Gotham

Abhishek Srivastava posted:
Hi,

Somebody recently asked me to implement the sizeof operator, i.e. to
write a function that accepts a parameter of any type, and without
using the sizeof operator, should be able to return the size occupied
by that datatype in memory in bytes. Thanks :)

Abhishek Srivastava


#include <cstddef>

template<class T>
struct SizeOfHelper {

T array[2];

};

#define SizeOf(T) offsetof(SizeOfHelper<T>, array[1])


I don't mind doing this homework question for people, because it's
utterly pointless.
 
T

Tom Widmer

Frederick said:
Abhishek Srivastava posted:

Hi,

Somebody recently asked me to implement the sizeof operator, i.e. to
write a function that accepts a parameter of any type, and without
using the sizeof operator, should be able to return the size occupied
by that datatype in memory in bytes. Thanks :)

Abhishek Srivastava



#include <cstddef>

template<class T>
struct SizeOfHelper {

T array[2];

};

#define SizeOf(T) offsetof(SizeOfHelper<T>, array[1])


I don't mind doing this homework question for people, because it's
utterly pointless.

Your implementation is incorrect in any case. offsetof is only defined
for POD types.

Tom
 
R

Rolf Magnus

Abhishek said:
Hi,

Somebody recently asked me to implement the sizeof operator, i.e. to
write a function that accepts a parameter of any type, and without
using the sizeof operator, should be able to return the size occupied
by that datatype in memory in bytes.

Interesting story.

What for?
 
F

Frederick Gotham

Tom Widmer posted:

Your implementation is incorrect in any case. offsetof is only defined
for POD types.


Yes, and thankfully, my type is a POD.
 
T

Tom Widmer

Frederick said:
Tom Widmer posted:




Yes, and thankfully, my type is a POD.

There's a second problem too; offsetof is defined for
member-designators, and "array[1]" isn't a member-designator.

Tom
 
T

Tom Widmer

Frederick said:
Tom Widmer posted:




Yes, and thankfully, my type is a POD.

Do you mean SizeOfHelper<T> is a POD type? It is a POD type if and
only if T is a POD type.

Tom
 
F

Frederick Gotham

Tom Widmer posted:
Do you mean SizeOfHelper<T> is a POD type? It is a POD type if and
only if T is a POD type.


Oh I see where you're coming from. Alas, my code is flawed.
 
A

Abhishek Srivastava

Tom said:
Do you mean SizeOfHelper<T> is a POD type? It is a POD type if and
only if T is a POD type.

Tom

Hi,

Thanks all :) Once again I reiterate, it was not a homework question.
It was actually an interview question. Atleast now I've got the answer
if not the job ... ;)

Thanks again,
Abhishek Srivastava
 
M

m_schellens

May I conclude that there was no real solution mentioned here so far?

offsetof:

only for member designators, POD


array:
what about alignment?


I think the right answer is that there is no universal replacement for
sizeof

Am I missing something?

Cheers,
Marc
 
F

Frederick Gotham

(e-mail address removed) posted:

array:
what about alignment?


(1) The first member of a POD has the same address as the POD itself.

(2) There's no padding between array elements.


So alignment isn't a problem.

If you're not allowed to create a temporary, then I think the following
is the closest thing you could have to "sizeof" for a type:

#define sizeof(T) \
(char const *)( ((T) const *)32 + 1 ) \
-(char const *)( ((T) const *)32 ) \


If, however, you want the size of an object, or perhaps the size of a
type (but you can use a temporary), then it's trivial:


#include <iostream>
#include <cstddef>

template<class T>
std::size_t SizeOf( T const &obj = T() )
{
return (char const *)(&obj + 1) - (char const *)(&obj);
}

int main()
{
unsigned i;

std::cout << SizeOf(i);

std::cout << SizeOf<unsigned>();
}
 
M

m_schellens

(1) The first member of a POD has the same address as the POD itself.

??? A POD has no members...
But I think I understand what you mean.
(2) There's no padding between array elements.

Is this really true? (Written in the standard?)
Hard to believe. If it is so, padding at all would be pretty useless.

Consider:

struct A { long int a; char b; long int c};

A arr[4];

(on a lets say 32bit machine with 32 bit long integer).
This way each element of arr would be aligned to another byte address.


Marc
 
F

Frederick Gotham

(e-mail address removed) posted:
??? A POD has no members...
But I think I understand what you mean.


struct I_am_a_POD {

char c;
int i;
void *p;
};

Is this really true? (Written in the standard?)
Hard to believe.


How else could we use pointers to iterate through an array?


#include <cassert>
#include <cstddef>

template<class T>
void ZeroArray( T *p, std::size_t const len )
{
assert(len >= 1);

T const * const p_over = p + len;

do
{
*p++ = T();
} while ( p != p_over );
}

int main()
{
double array[16] = {1,2,3,4,5,6,7,8,
9,10,11,12,13,14,15,16};

ZeroArray( array, sizeof(array) / sizeof(*array) );
}


Consider:

struct A { long int a; char b; long int c};

A arr[4];

(on a lets say 32bit machine with 32 bit long integer).
This way each element of arr would be aligned to another byte address.


Within an object of type "A", there may be padding between the members.

Within an array of objects of type "A", there may NOT be padding between
the elements.
 
A

Alf P. Steinbach

* Frederick Gotham:
If you're not allowed to create a temporary, then I think the following
is the closest thing you could have to "sizeof" for a type:

#define sizeof(T) \
(char const *)( ((T) const *)32 + 1 ) \
-(char const *)( ((T) const *)32 ) \

Prefer a template function to a macro. One problem with macros is that
they can easily conflict with language and standard library names. The
above one does, and that's a practical problem, not just a formal one.

If, however, you want the size of an object, or perhaps the size of a
type (but you can use a temporary), then it's trivial:


#include <iostream>
#include <cstddef>

template<class T>
std::size_t SizeOf( T const &obj = T() )
{
return (char const *)(&obj + 1) - (char const *)(&obj);
}

This isn't as trivial as you think.

1) The type may not have an accessible default constructor, which means
you cannot use T().

2) The type may not have an accessible copy constructor, which means you
cannot portably pass the argument by reference to const (yeah, in case
you wonder, currently having an accessible copy constructor is a
requirement for passing by reference to const, although that's so
infinitely silly that the requirement will be removed in C++0x).
 
M

Michiel.Salters

??? A POD has no members...

Wrong. struct X { int a,b } is a POD.
But I think I understand what you mean.


Is this really true? (Written in the standard?)
Hard to believe. If it is so, padding at all would be pretty useless.

It's useful, when you're mixing members with different alignment
requirements inside a struct. The fact that it's true isn't literally
in the
standard, but the standard requires that incrementing any T* by 1
gives an address that's sizeof(T) larger. I.e. for any T* ptr that
points to
a T (non-null), (char*)(ptr)+sizeof(T) = (char*)(ptr+1)

And thus, for any T* pt, sizeof(T)=(char*)(ptr+1)-(char*)(ptr) which
is the answer that the TS needed.

Arrays are not required, as any element is similar to an array of
length 1.

HTH,
Michiel Salters
 
F

Frederick Gotham

Alf P. Steinbach posted:

2) The type may not have an accessible copy constructor, which means you
cannot portably pass the argument by reference to const (yeah, in case
you wonder, currently having an accessible copy constructor is a
requirement for passing by reference to const, although that's so
infinitely silly that the requirement will be removed in C++0x).


I think that applies only if the argument being passed is an R-value:

class Arb {
private:

Arb( Arb const & );
Arb &operator=( Arb const & );

public:

Arb() {}
};


void Func(Arb const &) {}

int main()
{
Arb obj;

Func(obj); /* No problem */

Func( Arb() ); /* Compiler ERROR */
}


And that makes perfect sense to me if you consider the rules for binding
a const reference to an R-value:

"...a temporary of type 'cv1 T1' is created and initialized
from the initializer expression using the rules for a
non-reference copy initialization (8.5). The reference
is then bound to the temporary."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top