Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Base {}; sizeof(Base) == 1?

Reply
Thread Tools

Base {}; sizeof(Base) == 1?

 
 
moleskyca1@yahoo.com
Guest
Posts: n/a
 
      08-13-2006
This may be stupid question, but why is sizeof(Base) == 1 in:

int main(int argc, char* argv[])
{
class Base
{
};
cout << sizeof(Base) << endl;
return 0;
}

I guess I want to know what the 1 byte is for? There is no vptr here,
so why 1 byte?I checked FAQ and couldn't find answer.

 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      08-13-2006
* http://www.velocityreviews.com/forums/(E-Mail Removed):
> This may be stupid question, but why is sizeof(Base) == 1 in:
>
> int main(int argc, char* argv[])
> {
> class Base
> {
> };
> cout << sizeof(Base) << endl;
> return 0;
> }
>
> I guess I want to know what the 1 byte is for? There is no vptr here,
> so why 1 byte?I checked FAQ and couldn't find answer.


Needs a unique address.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
 
 
 
Daniel T.
Guest
Posts: n/a
 
      08-13-2006
In article <(E-Mail Removed). com>,
(E-Mail Removed) wrote:

> This may be stupid question, but why is sizeof(Base) == 1 in:
>
> int main(int argc, char* argv[])
> {
> class Base
> {
> };
> cout << sizeof(Base) << endl;
> return 0;
> }
>
> I guess I want to know what the 1 byte is for? There is no vptr here,
> so why 1 byte?I checked FAQ and couldn't find answer.


class Base { };

int main() {
Base bases[2];
assert( &bases[0] != &bases[1] );
}

How could the compiler ensure the above assertion is true if sizeof(
Base ) was 0?
 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      08-13-2006
Daniel T. wrote:

> In article <(E-Mail Removed). com>,
> (E-Mail Removed) wrote:
>
>> This may be stupid question, but why is sizeof(Base) == 1 in:
>>
>> int main(int argc, char* argv[])
>> {
>> class Base
>> {
>> };
>> cout << sizeof(Base) << endl;
>> return 0;
>> }
>>
>> I guess I want to know what the 1 byte is for? There is no vptr here,
>> so why 1 byte?I checked FAQ and couldn't find answer.

>
> class Base { };
>
> int main() {
> Base bases[2];
> assert( &bases[0] != &bases[1] );
> }
>
> How could the compiler ensure the above assertion is true if sizeof(
> Base ) was 0?


It could use infinitesimal pointer arithmetic: the size of an empty class
could be infinitesimally small. A pointers and sizeinformation would
contain an integer part and an infinitesimal part. Infinitesimal parts
would be ignored for allocation of memory, but they would be taken into
account for pointer arithmetic. The sizeof() operator would return the
integer part of a size.


Best

Kai-Uwe Bux
 
Reply With Quote
 
Frederick Gotham
Guest
Posts: n/a
 
      08-13-2006
moleskyca1 posted:

> This may be stupid question, but why is sizeof(Base) == 1 in:
>
> int main(int argc, char* argv[])
> {
> class Base
> {
> };
> cout << sizeof(Base) << endl;
> return 0;
> }
>
> I guess I want to know what the 1 byte is for? There is no vptr here,
> so why 1 byte?I checked FAQ and couldn't find answer.



To a large extent, C++ can be implemented in an "as if" way. Here's a
sample program which prints the integers 0 through 9:

#include <iostream>

using std::cout;

int main()
{
for(unsigned i = 0; i != 10; ++i)
{
cout << i << '\n';
}
}

In accordance with the C++ Standard, this program must print the integers 0
through 9... however it has much freedom in how it achieves this, just so
long as the program works "as if" it were coded the original way. For all
you know, the compiler may change it into:

cout << 0U << '\n';
cout << 1U << '\n';
cout << 2U << '\n';
cout << 3U << '\n';
cout << 4U << '\n';
cout << 5U << '\n';
cout << 6U << '\n';
cout << 7U << '\n';
cout << 8U << '\n';
cout << 9U << '\n';

Or perhaps even:

cout << "0\n1\n2\n3\n4\n5\n6\n7\n8\n9";

This "as if" principle gives compilers great freedom.

Every object (which is valid and has yet to be destroyed) must have a
unique address. For example:

struct MyStruct {};

int main()
{
MyStruct obj1;
MyStruct obj2;

assert(&obj1 != &obj2);
}

If every object must have a unique address, then the byte (or perhaps the
word) at that address cannot be used for anything else.

In accordance with this, "sizeof" might return 1, or maybe even 4.

However, in accordance with the "as if" principle, if you never take the
address of an object in any form, then there's no reason why it must
reserve memory. For instance, the compiler might change the following code:

struct A {};
struct B {};

void Func(A) {}
void Func(B) {}

int main()
{
A a; B b;

Func(a); Func(b);
}

into simply:

void FuncA() {}
void FuncB() {}

int main()
{
FuncA(); FuncB();
}

Lastly, "sizeof" shall never yield zero.

--

Frederick Gotham
 
Reply With Quote
 
Frederick Gotham
Guest
Posts: n/a
 
      08-13-2006
Frederick Gotham posted:

> If every object must have a unique address, then the byte (or perhaps
> the word) at that address cannot be used for anything else.



Actually, if you define the object as const, then perhaps the compiler may
feel free to store its own personal data at that address (data which your
program knows nothing about...)

--

Frederick Gotham
 
Reply With Quote
 
Salt_Peter
Guest
Posts: n/a
 
      08-14-2006

(E-Mail Removed) wrote:
> This may be stupid question, but why is sizeof(Base) == 1 in:
>
> int main(int argc, char* argv[])
> {
> class Base
> {
> };
> cout << sizeof(Base) << endl;
> return 0;
> }


corrected:
___
# include <iostream>
#include <ostream>

class Base
{
};

int main()
{
Base base;
std::cout << sizeof( base ) << std::endl;
}

>
> I guess I want to know what the 1 byte is for? There is no vptr here,
> so why 1 byte?I checked FAQ and couldn't find answer.


It isn't neccessarily 1 byte, that depends on the platform.

Is base not an instance of type Base?
Does it not therefore reside somewhere in memory in a concrete
location?
what you see is the "this" parameter.
In otherwords, the programmer needs not track where base is because
that instance already knows where it is located in memory.

What if i defined Base like so...

class Base
{
int m_n;
public:
Base(int n) : m_n( n ) { }
~Base() { }
int get() const { return m_n; }
};

....how would the program know which Base is which?

int main()
{
Base base0( 10 );
Base base1( 20 );

std::cout << "base0 = " << base0.get() << std::endl;
std::cout << "base1 = " << base1.get() << std::endl;
}

There is only one get() function placed in memory.
However, get() receives the 'this' parameter - since get() is a member
function.
And that seemingly obscure this parameter is the key.
The call to get() therefore receives the instances' address
transparently.

Of course, you can make get() to be a non-member:

int get( Base* this) { return this->m_n; }

int main()
{
Base base( 1 );
std::cout << get( &base );
}

But all of a sudden, the encapsulated integer ( m_n) is no longer
private.
There is also a side-effect involved thats beyond the scope here.

The cost of that 1 extra byte you saw before solves a whole littany of
bugs and affords the programmer effective encapsulation + clear code.

 
Reply With Quote
 
Frederick Gotham
Guest
Posts: n/a
 
      08-14-2006
Salt_Peter posted:

> corrected:



It was just a code snippet -- no need for pedantry.


> What if i defined Base like so...
>
> class Base
> {
> int m_n;
> public:
> Base(int n) : m_n( n ) { }
> ~Base() { }
> int get() const { return m_n; }
> };
>
> ...how would the program know which Base is which?



This example has nothing to do with empty classes. Nonetheless, I would
expect the following to evaluate to true:

(void const*)&base == (void const*)&base.m_n


> The cost of that 1 extra byte you saw before solves a whole littany of
> bugs and affords the programmer effective encapsulation + clear code.



No it doesn't. The question was about empty classes, i.e.:

class MyClass {};

You've used examples which have member data... so *of course* their size
won't be zero.

--

Frederick Gotham
 
Reply With Quote
 
Jerry Coffin
Guest
Posts: n/a
 
      08-14-2006
In article <ebnu57$9jm$(E-Mail Removed)>, (E-Mail Removed)
says...

[ ... ]

> It could use infinitesimal pointer arithmetic: the size of an empty class
> could be infinitesimally small. A pointers and sizeinformation would
> contain an integer part and an infinitesimal part. Infinitesimal parts
> would be ignored for allocation of memory, but they would be taken into
> account for pointer arithmetic. The sizeof() operator would return the
> integer part of a size.


How exactly would you do that without storing the "infinitesimal" part
as data in each object? If you did store it as data in the object, it
appears that on a typical machine it would have to be _larger_ than one
byte to distinguish more than 256 objects of that type. In fact, it
would generally be on the same general size as an address, which is
usually larger than a byte, by a factor of at least 2, often 4, and
sometimes 8.

--
Later,
Jerry.

The universe is a figment of its own imagination.
 
Reply With Quote
 
Jerry Coffin
Guest
Posts: n/a
 
      08-14-2006
In article <xKRDg.12640$(E-Mail Removed)>, (E-Mail Removed)
says...
> Salt_Peter posted:


[ ... ]

> > class Base
> > {
> > int m_n;
> > public:
> > Base(int n) : m_n( n ) { }
> > ~Base() { }
> > int get() const { return m_n; }
> > };


[ ... ]

> This example has nothing to do with empty classes. Nonetheless, I would
> expect the following to evaluate to true:
>
> (void const*)&base == (void const*)&base.m_n


With an aggregate, that's basically guaranteed. As-is, there's a good
chance, but no certainty. At least with some implememtations, it would
NOT be true if Base contained any virtual functions.

--
Later,
Jerry.

The universe is a figment of its own imagination.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
sizeof(EmptyStruct) in C and C++ (was: Base {}; sizeof(Base) == 1?) Alex Vinokur C Programming 7 08-14-2006 04:57 PM
Access of base class' private base class: qualification required, why Alf P. Steinbach C++ 6 09-03-2005 04:03 PM
Format of compiler generated derived destructor when base has 'virtual ~base() throw():" qazmlp C++ 1 04-10-2005 03:09 PM
Virtual function 'BasicMidReader::~BasicMidReader()' conflicts with base class 'base 'TMemoryStream' tomek C++ 2 12-01-2003 06:31 AM
Virtual function 'BasicMidReader::~BasicMidReader()' conflicts with base class 'base 'TMemoryStream' tomek C++ 3 11-30-2003 12:18 AM



Advertisments