473,385 Members | 1,620 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Bit-Pattern of Representation of Objects

I was struggling to come up with a way to discern the actual
bit patterns of the representations of C++ objects (esp.
objects of small built-in types), and I came up with the
following mess. But I'm wondering, is there an easier way
to do this? This seems so klunky.

#include <iostream>
#include <cmath>
template<typename T>
void Binary(T const & object)
{
size_t size = 8 * sizeof(object); // Size of object in bits.
unsigned long long int mask =
static_cast<unsigned long long int>
(pow(2.0, static_cast<double>(size - 1)) + 0.1);
unsigned long long int pattern =
*reinterpret_cast<const unsigned long long int*>(&object);
for( ; mask 0 ; mask >>= 1)
{
if(pattern & mask) std::cout << "1";
else std::cout << "0";
}
std::cout << std::endl;
return;
}
--
Cheers,
Robbie Hatley
East Tustin, CA, USA
lone wolf intj at pac bell dot net
(put "[usenet]" in subject to bypass spam filter)
http://home.pacbell.net/earnur/
Jul 16 '06 #1
15 1998
* Robbie Hatley:
I was struggling to come up with a way to discern the actual
bit patterns of the representations of C++ objects (esp.
objects of small built-in types), and I came up with the
following mess. But I'm wondering, is there an easier way
to do this? This seems so klunky.

#include <iostream>
#include <cmath>
template<typename T>
void Binary(T const & object)
{
size_t size = 8 * sizeof(object); // Size of object in bits.
Use CHAR_BITS or whatever it's called: a byte isn't necessarily 8 bits.

unsigned long long int mask =
C++ does not have a 'long long' type, yet.

static_cast<unsigned long long int>
(pow(2.0, static_cast<double>(size - 1)) + 0.1);
Use left shift operator.

unsigned long long int pattern =
*reinterpret_cast<const unsigned long long int*>(&object);
You don't know that sizeopf(object) <= sizeof(long long).

for( ; mask 0 ; mask >>= 1)
{
if(pattern & mask) std::cout << "1";
else std::cout << "0";
std::cout << !!(pattern & mask);

}
std::cout << std::endl;
return;
Unnecessary 'return'.
}

--
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?
Jul 16 '06 #2
Robbie Hatley posted:
I was struggling to come up with a way to discern the actual
bit patterns of the representations of C++ objects

Here's some code I wrote recently if you're interested:

#include <cstddef>
#include <cassert>
#include <climits>
#include <ostream>

void PrintBits(void const * const mem,size_t amount_bytes,std::ostream &os)
{
assert( mem );
assert( amount_bytes );

char static str[CHAR_BIT + 1] = {};

unsigned char const *p = reinterpret_cast<unsigned char const*>(mem);

do
{
unsigned const byte_val = *p++;

char *pos = str;

unsigned to_and_with = 1U << CHAR_BIT - 1;

do *pos++ = byte_val & to_and_with ? '1' : '0';
while(to_and_with >>= 1);

os << str;

} while (--amount_bytes);
}
template<class T>
inline void PrintObjBits(T const &obj,std::ostream &os)
{
PrintBits(&obj,sizeof obj,os);
}
#include <iostream>

int main()
{
long double array[4] = { 241.126, 632.225, 2662.2523, 23345.2352 };

PrintObjBits(array,std::cout);
}

--

Frederick Gotham
Jul 16 '06 #3
Robbie Hatley wrote:
I was struggling to come up with a way to discern the actual
bit patterns of the representations of C++ objects (esp.
objects of small built-in types), and I came up with the
following mess. But I'm wondering, is there an easier way
to do this? This seems so klunky.
Copy the object into a suitably sized array of unsigned char, then dump
the unsigned chars in hex. If you really need binary rather than hex,
the conversion is a fairly simple exercise.
Jul 16 '06 #4

"Alf P. Steinbach" <al***@start.nowrote:
Robbie Hatley wrote:
...
size_t size = 8 * sizeof(object); // Size of object in bits.

Use CHAR_BITS or whatever it's called: a byte isn't necessarily 8 bits.
"CHAR_BIT". True. However, the vast majority of the world's computers,
especially non-mainframe computers, use 8-bit bytes. That's pretty
ubiquitous.

But to be pedantic, I'll do:

size_t size = CHAR_BIT * sizeof(object);
unsigned long long int mask =

C++ does not have a 'long long' type, yet.
Not yet, but the committe is working on it. Besides, many
C++ compilers jumped the gun and provided long long and
unsigned long long years ago, so they're actually quite common.
static_cast<unsigned long long int>
(pow(2.0, static_cast<double>(size - 1)) + 0.1);

Use left shift operator.
Great idea! Thanks! Saves the inefficient pow() call.
I'll do this:

unsigned long long mask = unsigned long long(1) << size - 1;
unsigned long long int pattern =
*reinterpret_cast<const unsigned long long int*>(&object);

You don't know that sizeopf(object) <= sizeof(long long).
Yes, I do. Think about it. Unsigned long long has a maximum
value of over 18 quintillion, so it can express the size of
an object of over 18EB. ("EB" is "exabytes". One exabyte
is 10^18 bytes, or 1 billion gigabytes.) You give me a computer
with 18EB of memory, I'll give you $500 for it. :-) Of course,
pointers would then need to become unsigned long long in order
to address that much memory space, but it would be worth it.
(Caveat: that's assuming long long is at least 64 bits. If it's
not, the implimentor should not have bothered implimenting it.)

Anyway, thanks for the tips!

--
Cheers,
Robbie Hatley
East Tustin, CA, USA
lone wolf intj at pac bell dot net
(put "[usenet]" in subject to bypass spam filter)
http://home.pacbell.net/earnur/
Jul 17 '06 #5

A few minutes ago, I wrote:
"Alf P. Steinbach" <al***@start.nowrote:
Robbie Hatley wrote:
unsigned long long int pattern =
*reinterpret_cast<const unsigned long long int*>(&object);
You don't know that sizeopf(object) <= sizeof(long long).

Yes, I do. Think about it. Unsigned long long has a maximum
value of over 18 quintillion, so it can express the size of
an object of over 18EB...
Oops, I blew it. I confused "size expressible by long long" (which
is about 18 quintillion bytes) with "size of long long" (which is
only 8 bytes on most implimentations). I must be getting sleepy.

So, my little program, as written, can only handle objects up to
8 bytes in length, not 18EB. Oh, well. I was only off by about
17 orders of magnitude. Not bad for a Sunday afternoon.
--
Cheers,
Robbie Hatley
East Tustin, CA, USA
lone wolf intj at pac bell dot net
(put "[usenet]" in subject to bypass spam filter)
http://home.pacbell.net/earnur/
Jul 17 '06 #6
"Frederick Gotham" wrote:
#include <cstddef>
#include <cassert>
#include <climits>
#include <ostream>

void PrintBits(void const * const mem,size_t amount_bytes,std::ostream &os)
{
assert( mem );
assert( amount_bytes );

char static str[CHAR_BIT + 1] = {};

unsigned char const *p = reinterpret_cast<unsigned char const*>(mem);

do
{
unsigned const byte_val = *p++;

char *pos = str;

unsigned to_and_with = 1U << CHAR_BIT - 1;

do *pos++ = byte_val & to_and_with ? '1' : '0';
while(to_and_with >>= 1);

os << str;

} while (--amount_bytes);
}
template<class T>
inline void PrintObjBits(T const &obj,std::ostream &os)
{
PrintBits(&obj,sizeof obj,os);
}
#include <iostream>

int main()
{
long double array[4] = { 241.126, 632.225, 2662.2523, 23345.2352 };

PrintObjBits(array,std::cout);
}
Yes, that's much better than my approach. No limit on the size
of the object that way, other than that you're assuming it's
contiguous in memory.

I like the nested do loops, which break the problem first into
bytes, then into bits. And the fact that it just riffles through
the existing data in-place, without any copying. Cool. Thanks
for sharing this.

--
Cheers,
Robbie Hatley
East Tustin, CA, USA
lone wolf intj at pac bell dot net
(put "[usenet]" in subject to bypass spam filter)
http://home.pacbell.net/earnur/
Jul 17 '06 #7
Robbie Hatley wrote:
>
"Alf P. Steinbach" <al***@start.nowrote:
>Robbie Hatley wrote:
...
size_t size = 8 * sizeof(object); // Size of object in bits.

Use CHAR_BITS or whatever it's called: a byte isn't necessarily 8 bits.

"CHAR_BIT". True. However, the vast majority of the world's computers,
especially non-mainframe computers, use 8-bit bytes. That's pretty
ubiquitous.

But to be pedantic, I'll do:

size_t size = CHAR_BIT * sizeof(object);
unsigned long long int mask =

C++ does not have a 'long long' type, yet.

Not yet, but the committe is working on it. Besides, many
C++ compilers jumped the gun and provided long long and
unsigned long long years ago, so they're actually quite common.
static_cast<unsigned long long int>
(pow(2.0, static_cast<double>(size - 1)) + 0.1);

Use left shift operator.

Great idea! Thanks! Saves the inefficient pow() call.
I'll do this:

unsigned long long mask = unsigned long long(1) << size - 1;
unsigned long long int pattern =
*reinterpret_cast<const unsigned long long int*>(&object);

You don't know that sizeopf(object) <= sizeof(long long).

Yes, I do. Think about it. Unsigned long long has a maximum
value of over 18 quintillion, so it can express the size of
an object of over 18EB. ("EB" is "exabytes". One exabyte
is 10^18 bytes, or 1 billion gigabytes.) You give me a computer
with 18EB of memory, I'll give you $500 for it. :-)
You are aguing

sizeof(object) <= std::max<long long>()

not

sizeof( object ) <= sizeof( long long )

Note sizeof(long long) maybe as low as 8 (or even 1 if chars are really
huge).

Anyway, what happens in the code is that you try to store the bit pattern of
object in a variable of type unsigned long long, whose size might be too
small. So what about:

#include <cstddef>
#include <climits>

template < typename T >
struct bit_pattern {

static std::size_t const size = sizeof( T );

typedef unsigned char const * address;

static
address mem_location ( T const & t ) {
return ( reinterpret_cast< address >( &t ) );
}

template < typename OutIter >
static
OutIter dump_bits ( T const & t, OutIter where ) {
address loc = mem_location( t );
for ( std::size_t index = 0; index < size; ++index ) {
unsigned char c = loc[index];
unsigned char mask = 1;
for ( std::size_t bit_pos = 0; bit_pos < CHAR_BIT; ++ bit_pos ) {
where = ( ( c & mask ) != 0 );
++ where;
mask <<= 1;
}
}
return ( where );
}

}; // bit_pattern

template < typename T, typename OutIter >
OutIter dump_bits ( T const & t, OutIter where ) {
return ( bit_pattern<T>::dump_bits( t, where ) );
}

#include <iostream>
#include <iterator>
int main ( void ) {
int i = 5;
std::ostream_iterator< bool bool_writer ( std::cout );
dump_bits( i, bool_writer );
std::cout << '\n';
}
Best

Kai-Uwe Bux
Jul 17 '06 #8
"Kai-Uwe Bux" wrote:
Robbie Hatley wrote:

"Alf P. Steinbach" <al***@start.nowrote:
You don't know that sizeopf(object) <= sizeof(long long).
Yes, I do. Think about it. Unsigned long long has a maximum
value of over 18 quintillion, so it can express the size of
an object of over 18EB. ("EB" is "exabytes". One exabyte
is 10^18 bytes, or 1 billion gigabytes.) You give me a computer
with 18EB of memory, I'll give you $500 for it. :-)

You are aguing

sizeof(object) <= std::max<long long>()

not

sizeof( object ) <= sizeof( long long )

Yes, I relalized that a minute later. Really stupid error on my
part. (See my other post on that.)

#include <cstddef>
#include <climits>

template < typename T >
struct bit_pattern {

static std::size_t const size = sizeof( T );

typedef unsigned char const * address;

static
address mem_location ( T const & t ) {
return ( reinterpret_cast< address >( &t ) );
}

template < typename OutIter >
static
OutIter dump_bits ( T const & t, OutIter where ) {
address loc = mem_location( t );
for ( std::size_t index = 0; index < size; ++index ) {
unsigned char c = loc[index];
unsigned char mask = 1;
for ( std::size_t bit_pos = 0; bit_pos < CHAR_BIT; ++ bit_pos ) {
where = ( ( c & mask ) != 0 );
++ where;
mask <<= 1;
}
}
return ( where );
}

}; // bit_pattern

template < typename T, typename OutIter >
OutIter dump_bits ( T const & t, OutIter where ) {
return ( bit_pattern<T>::dump_bits( t, where ) );
}

#include <iostream>
#include <iterator>
int main ( void ) {
int i = 5;
std::ostream_iterator< bool bool_writer ( std::cout );
dump_bits( i, bool_writer );
std::cout << '\n';
}
Hmmm... Really heavy-weight C++ solution, as opposed to Frederick
Gotham's C-flavored solution. A template function which invokes
a template member function in a template struct. Yikes.

I notice that in both dump_bits functions, OutIter is passed by
value instead of by ref. Is that a mistake, or is that by design?
It will cause the three copies of OutIter -- argument, parameter,
return -- to be independent of each other. I suppose there's an
advantage there, because a calling function could maintain an
"original entry point" iterator, as well as a "where we ended up"
iterator returned from dump_bits().

On second thought, I think that's a mistake, not a virtue. Since
this is a stream iterator, we probably DON'T want the ability to
go back and overwrite some earlier part of the stream. So I'm
thinking OutIter should be passed by reference.

I can't say I understand everything I'm looking at here. Like
THIS line of code:

std::ostream_iterator< bool bool_writer ( std::cout );

I've never used stream iterators before. So this is basically
making a bool-writing ostream iterator and connecting it to cout?
How do you use that, something like the following?

*bool_writer = ( /* boolean value */ );
++bool_writer;

But I notice in your code, you have

where = ( ( c & mask ) != 0 );
++where;

Shouldn't that be more like the following?

*where = ( ( c & mask ) != 0 );
++where;
--
Cheers,
Robbie Hatley
East Tustin, CA, USA
lone wolf intj at pac bell dot net
(put "[usenet]" in subject to bypass spam filter)
http://home.pacbell.net/earnur/
Jul 17 '06 #9
Robbie Hatley wrote:
"Kai-Uwe Bux" wrote:
>Robbie Hatley wrote:
>
"Alf P. Steinbach" <al***@start.nowrote:

You don't know that sizeopf(object) <= sizeof(long long).

Yes, I do. Think about it. Unsigned long long has a maximum
value of over 18 quintillion, so it can express the size of
an object of over 18EB. ("EB" is "exabytes". One exabyte
is 10^18 bytes, or 1 billion gigabytes.) You give me a computer
with 18EB of memory, I'll give you $500 for it. :-)

You are aguing

sizeof(object) <= std::max<long long>()

not

sizeof( object ) <= sizeof( long long )


Yes, I relalized that a minute later. Really stupid error on my
part. (See my other post on that.)

>#include <cstddef>
#include <climits>

template < typename T >
struct bit_pattern {

static std::size_t const size = sizeof( T );

typedef unsigned char const * address;

static
address mem_location ( T const & t ) {
return ( reinterpret_cast< address >( &t ) );
}

template < typename OutIter >
static
OutIter dump_bits ( T const & t, OutIter where ) {
address loc = mem_location( t );
for ( std::size_t index = 0; index < size; ++index ) {
unsigned char c = loc[index];
unsigned char mask = 1;
for ( std::size_t bit_pos = 0; bit_pos < CHAR_BIT; ++ bit_pos ) {
where = ( ( c & mask ) != 0 );
++ where;
mask <<= 1;
}
}
return ( where );
}

}; // bit_pattern

template < typename T, typename OutIter >
OutIter dump_bits ( T const & t, OutIter where ) {
return ( bit_pattern<T>::dump_bits( t, where ) );
}

#include <iostream>
#include <iterator>
int main ( void ) {
int i = 5;
std::ostream_iterator< bool bool_writer ( std::cout );
dump_bits( i, bool_writer );
std::cout << '\n';
}

Hmmm... Really heavy-weight C++ solution, as opposed to Frederick
Gotham's C-flavored solution. A template function which invokes
a template member function in a template struct. Yikes.
That is just to allow for automatic type deduction. Moreover, there is a
certain amount of overkill here. One could just do:

#include <cstddef>
#include <climits>

typedef unsigned char const * address;

template < typename T >
address mem_location ( T const & t ) {
return ( reinterpret_cast< address >( &t ) );
}

template < typename T, typename OutIter >
OutIter dump_bits ( T const & t, OutIter where ) {
address loc = mem_location( t );
for ( std::size_t index = 0; index < sizeof(T); ++index ) {
unsigned char c = loc[index];
unsigned char mask = 1;
for ( std::size_t bit_pos = 0; bit_pos < CHAR_BIT; ++ bit_pos ) {
*where = ( ( c & mask ) != 0 );
++ where;
mask <<= 1;
}
}
return ( where );
}

#include <iostream>
#include <iterator>

int main ( void ) {
int i = 5;
std::ostream_iterator< bool bool_writer ( std::cout );
dump_bits( i, bool_writer );
std::cout << '\n';
}
The main difference is that I use an output iterator in the interface for
dump_bits(). This way, one could use this function to initialize a vector
or any other sequence.

I notice that in both dump_bits functions, OutIter is passed by
value instead of by ref. Is that a mistake, or is that by design?
It will cause the three copies of OutIter -- argument, parameter,
return -- to be independent of each other. I suppose there's an
advantage there, because a calling function could maintain an
"original entry point" iterator, as well as a "where we ended up"
iterator returned from dump_bits().

On second thought, I think that's a mistake, not a virtue. Since
this is a stream iterator, we probably DON'T want the ability to
go back and overwrite some earlier part of the stream. So I'm
thinking OutIter should be passed by reference.
In this regard, I am just following the precedent set by the algorithms from
the standard library: all iterators are passed by value. This implies that
iterator object better be designed to be small.
>
I can't say I understand everything I'm looking at here. Like
THIS line of code:

std::ostream_iterator< bool bool_writer ( std::cout );

I've never used stream iterators before. So this is basically
making a bool-writing ostream iterator and connecting it to cout?
Yep.
How do you use that, something like the following?

*bool_writer = ( /* boolean value */ );
++bool_writer;
Yep.
But I notice in your code, you have

where = ( ( c & mask ) != 0 );
++where;

Shouldn't that be more like the following?

*where = ( ( c & mask ) != 0 );
++where;
Yes, that's a typo. Thanks for catching that. I wonder why it compiled and
produced the expected output.
Best

Kai-Uwe Bux
Jul 17 '06 #10
* Kai-Uwe Bux:
...
ASIPW (Academic Spanner In Practical Wheel): how well does your code
work with diamond pattern virtual inheritance? <g>

Actually it's potentially far worse than that, from an academic or
language lawyer point of view, depending on which committee member
faction one favors.

IIRC, David Abrahams argued that for /any/ non-POD class the compiler is
allowed to distribute an object's value representation hither and dither
in memory, with just some pointers or offsets here and there to connect
things (essentially that's what done for the case mentioned above, but
you don't expect it elsewhere in practice), and further that this was
inherent in the phrase "region of storage" (or memory, whatever it was,
look up the definition of "object" in the standard), which, as he saw
it, was not necessarily a contigous region but rather any set of bytes.
I.e., that even a /variable/, a named object, is not necessarily
contained in the set of bytes from its start address through sizeof
bytes. My own view is, perhaps needless to say, that it is.

--
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?
Jul 17 '06 #11
Robbie Hatley posted:
No limit on the size of the object that way, other than that you're
assuming it's contiguous in memory.

Hmm... (give my brain a minute to mull that over).

Of course, in C++, an object can be really "fancy", and have all sorts of
constructors and overloaded operators, but *ultimately*, the object itself
is stored as a simple sequence of bits in memory.

Is it not a fundamental assumption that these bits are contiguous?

I like the nested do loops, which break the problem first into
bytes, then into bits.

If ever you have a sleepless night and want to expend some brain power, you
could become an efficiency junky and unroll whatever loops you can. Instead
of having:

unsigned to_and_with = 1U << CHAR_BIT - 1;

do *pos++ = byte_val & to_and_with ? '1' : '0';
while(to_and_with >>= 1);
We could have:
#if CHAR_BIT 8
for(unsigned to_and_with = 1U << CHAR_BIT - 1;;byte_val >>= 1)
{
*pos++ = byte_val & to_and_with ? '1' : '0';

if(256 == byte_val) break;
}

#endif

*pos++ = byte_val & 128 ? '1' : '0';
*pos++ = byte_val & 64 ? '1' : '0';
*pos++ = byte_val & 32 ? '1' : '0';
*pos++ = byte_val & 16 ? '1' : '0';
*pos++ = byte_val & 8 ? '1' : '0';
*pos++ = byte_val & 4 ? '1' : '0';
*pos++ = byte_val & 2 ? '1' : '0';
*pos++ = byte_val & 1 ? '1' : '0';
(Of course, we like to hope the compiler will do this for us.)

And the fact that it just riffles through
the existing data in-place, without any copying. Cool.

If I were to go for extreme efficiency, I would only make one final output,
rather than outputting each byte one by one.

Thanks for sharing this.

You're welcome. :)
--

Frederick Gotham
Jul 17 '06 #12
* Frederick Gotham:
Robbie Hatley posted:
>No limit on the size of the object that way, other than that you're
assuming it's contiguous in memory.

Hmm... (give my brain a minute to mull that over).

Of course, in C++, an object can be really "fancy", and have all sorts of
constructors and overloaded operators, but *ultimately*, the object itself
is stored as a simple sequence of bits in memory.

Is it not a fundamental assumption that these bits are contiguous?
No (although for a POD they are, and in practice they are except when
virtual inheritance is involved).

--
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?
Jul 17 '06 #13
Alf P. Steinbach posted:
>Of course, in C++, an object can be really "fancy", and have all sorts
of constructors and overloaded operators, but *ultimately*, the object
itself is stored as a simple sequence of bits in memory.

Is it not a fundamental assumption that these bits are contiguous?

No (although for a POD they are, and in practice they are except when
virtual inheritance is involved).

If we have an object, there's two operators we can apply to it which will
give us all the info about how it's stored in memory:

Address-of operator: &obj
sizeof operator: sizeof obj

Let's say that the former gives us a memory location of:

1032

And that the latter gives us a size of:

8

Can we not therefore assume that the object's bits are dispersed between
the following memory locations:

1032 through 1040
Therefore, if we print out all the bits from 1032 through 1040, are we not
printing out all of the object's bits?
--

Frederick Gotham
Jul 17 '06 #14
Alf P. Steinbach wrote:
* Kai-Uwe Bux:
>...

ASIPW (Academic Spanner In Practical Wheel): how well does your code
work with diamond pattern virtual inheritance? <g>
Perfectly fine: the requirements were a little vague. <g>
Actually it's potentially far worse than that, from an academic or
language lawyer point of view, depending on which committee member
faction one favors.

IIRC, David Abrahams argued that for /any/ non-POD class the compiler is
allowed to distribute an object's value representation hither and dither
in memory, with just some pointers or offsets here and there to connect
things (essentially that's what done for the case mentioned above, but
you don't expect it elsewhere in practice), and further that this was
inherent in the phrase "region of storage" (or memory, whatever it was,
look up the definition of "object" in the standard), which, as he saw
it, was not necessarily a contigous region but rather any set of bytes.
I.e., that even a /variable/, a named object, is not necessarily
contained in the set of bytes from its start address through sizeof
bytes. My own view is, perhaps needless to say, that it is.
I wonder whether that interesting point of view implies that, say,
malloc(sizeof(T)) with a following placement new cannot be used to
construct an object of type T because the layout of T may require its
sizeof(T) bytes to be scattered in memory in a peculiar non-contiguous way.
That would be of interest for anybody using std::vector<Twith a custom
allocator.
Best

Kai-Uwe Bux
Jul 17 '06 #15
* Frederick Gotham:
Alf P. Steinbach posted:
>>Of course, in C++, an object can be really "fancy", and have all sorts
of constructors and overloaded operators, but *ultimately*, the object
itself is stored as a simple sequence of bits in memory.

Is it not a fundamental assumption that these bits are contiguous?
No (although for a POD they are, and in practice they are except when
virtual inheritance is involved).


If we have an object, there's two operators we can apply to it which will
give us all the info about how it's stored in memory:

Address-of operator: &obj
sizeof operator: sizeof obj

Let's say that the former gives us a memory location of:

1032

And that the latter gives us a size of:

8

Can we not therefore assume that the object's bits are dispersed between
the following memory locations:

1032 through 1040
Therefore, if we print out all the bits from 1032 through 1040, are we not
printing out all of the object's bits?
struct Base{ char id; Base( char anId = '?' ): id(anId) {} };
struct A: virtual Base { int x; A(): x( 1 ) {} };
struct B: virtual Base { int y; B(): y( 2 ) {} };
struct Derived: A, B { Derived( char anId ): Base( anId ) {} };

void showBits( B const& o )
{
// Assumption of o being contigous is made.
}

int main()
{
B b;
Derived d;

showBits( b ); // Possibly OK.
showBits( d ); // Definitely bad.
}

--
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?
Jul 17 '06 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
by: Amy DBA | last post by:
I've been asked to administer a DB2 V 8 (32-bit install) on a Solaris 64-bit platform. It seems like whomever installed DB2 on the server, goofed for not installing DB2 v8 64 bit. Do I understand...
12
by: Jean-Marc Blaise | last post by:
Hi, Is it worth to use 64-bit DB2 instances on a 32-bit kernel, in terms of: - performance - configuration (go beyond the 256 Mb segment for private mem, 1.75 Gb for Bufferpools) - other ? ...
19
by: Ross A. Finlayson | last post by:
Hi, I hope you can help me understand the varargs facility. Say I am programming in ISO C including stdarg.h and I declare a function as so: void log_printf(const char* logfilename, const...
11
by: JDeats | last post by:
1. Will there be different 64-bit .NET implementations for Intel and AMD 64-bit processors or will they share a common 64-bit CLR? 2. Will .NET managed code compiled for the 32-bit CLR be binary...
58
by: Larry David | last post by:
Ok, first of all, let's get the obvious stuff out of the way. I'm an idiot. So please indulge me for a moment. Consider it an act of "community service".... What does "64bit" mean to your friendly...
4
by: tommydkat | last post by:
Well, I've finally gotten UDB 8.2 FixPak 3 up and running on my HP-UX 11i system, thanks to Mr McBride and IBM support. :) I created a 32-bit instance and that's running just fine. However, I...
14
by: =?Utf-8?B?R2Vvcmdl?= | last post by:
Hello everyone, I am using C# to develop DLL using Visual Studio 2005 and .Net 2.0, and I have no idea of how to make my DLL work with applications on 64-bit platform. Above all, I do not...
1
by: Chuck Chopp | last post by:
I have some code that is being built on the following: Windows Server 2003, both 32-bit & 64-bit editions Windows Vista, both 32-bit & 64-bit editions Windows Server 2008, both 32-bit & 64-bit...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.