Re: Bit-Pattern of Representation of Objects
Robbie Hatley wrote:
"Kai-Uwe Bux" wrote:
Robbie Hatley wrote:
"Alf P. Steinbach" <alfps@start.no> wrote:
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