Solved

Arrays of bits

Posted on 2002-07-24
14
281 Views
Last Modified: 2012-05-04
I've been trying to create an array of bits so that I can manipulate each bit of a particular data type.  I've been somewhat successfull, however the values for the bits in the array don't match the value input.  I don't know what the problem is.  Something like this:

struct BITS_32
{
   unsigned bits : 1;
};

union BITS
{
   int int32;
   BITS_32 bits[32];
}bits32;

bits32.int32 = 123456;

for (int i = 0; i < 32; i++)
{
   cout << "bit" << i << ": " << bits32.bits[i] << endl;
}


This doesn't give the write output.  Does anybody know why?  Thanks for the help.

MacLeod
0
Comment
Question by:MacLeod
  • 6
  • 4
  • 4
14 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 7175098
>>Does anybody know why?

That's because the size of one 'struct BITS_32' is at least 'sizeof(unsigned)' - this approach won't work.

I'd suggest to take a look into STL's 'bitset'.
0
 

Author Comment

by:MacLeod
ID: 7175343
I would take a look at <bitset>, but I want to use this with a compiler has no STL support.  So that's why I'm trying maybe a somewhat goofy approach.

So the struct is at least 32 bits?  That makes sense.  I don't know why I didn't catch that earlier.  Is it at all possible to do this without the STL?

MacLeod
0
 
LVL 86

Expert Comment

by:jkr
ID: 7175437
>>So the struct is at least 32 bits?

You could reduce that to 8 bits by using

struct BITS_32
{
  unsigned char bits : 1;
};

But that won't help either.

>>but I want to use this with a compiler has no STL support

STL is not 'supported' by any compiler, all that is necessary is that the compiler has to support templates. You could get any STL from www.stlport.org

>>Is it at all possible to do this without the STL?

It is, but it's cumbersome. You could


struct BITS_32
{
  unsigned long bit0 : 1;
  // ...
  unsigned long bit31 : 1;

  bool operator [] ( unsigned int i) {

   switch ( i) {

   case 0: return bit0;

   // ...
  }
 }
};

0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 

Author Comment

by:MacLeod
ID: 7175564
That's is true no compiler supports it directly.  The particular compiler I have I could get STL for, but I don't have permissions to change it and I wanted to see if I could do it another way anyway, so this looks like it's following my peculiar train-of-thought.  So I'd overload the [] operator to be able to access the different 32 bit fields in the struct.  That makes sense.  I'll try this out and see how it works for me.
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 7175671
No, don't, bitfields are BAD and you may get unexpected behaviour. There are numerous reports of talented coders that almost tried to kill themselves over bugs they couldn't get hold of. In most of those cases they were hidden in bitfields. You don't believe me? Take a look at this:
http://www.flipcode.com/cgi-bin/msg.cgi?showThread=00002327&forum=general&id=-1

Go with std::bitset if you want to be safe. Also, jkr's suggestions don't necessarily work. Data alignment is usually 32bits on PC's. If you are using msvc you could change it to 8bit by

#pragma pack( push )
#pragma pack( 1 )
// your structs go here
#pragma pack( pop )

Or if you can't use STL and now you will never use more than 32 bits you could use this:

struct BITS_32 {
private:
    unsigned int _bits;
public:
    BITS_32() : _bits( 0 ) {}
    void set_bit( unsigned int index ) { _bits |= ( 1 << index ); }
    void reset_bit( unsigned int index ) { _bits &= ~( 1 << index ); }
    bool get_bit( unsigned int index ) { return( 0 != ( _bits & ( 1 << index ) ); }
};

All indices are 0-based. No range checking is performed. Expand on it if you need to, but stay away from bitfields as if your life depended on it.
0
 

Author Comment

by:MacLeod
ID: 7175912
Actually, jkr's suggestions are working great so far.  I just have one last hurdle to overcome, setting the bit.  I've gotten myself itno a little hairy mess I think with this.  I'll figure it out though.  At least I'm finally getting the correct values for the bits in the bit fields.

Your suggestion would work except I'm trying not to use any bitwise operators.  Yes, I'm insane and crazy and all the above.  I have some spare time and wanted to see if I could drive myself nuts.  I'm doing a pretty good job, however I'm extremely persistent and WILL figure something out.  Basically I'm writting my own bitwise operators and I'm not too concerned about efficiency at this point.  I think I should raise the points on this one a bit for the great help I'm getting.
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 7175945
Setting the bits:

void SetBit( unsigned int index ) { this->operator[]( index ) = 1; }

and change the

bool operator []...
to
bool& operator []...

If driving yourself nuts is your major goal, then, by all means, use bitfields. There is hardly any other field where you could achieve this that easily than with bitfields...

One question though, why exactly are you trying to NOT use any bitwise operators?
0
 
LVL 86

Accepted Solution

by:
jkr earned 300 total points
ID: 7176148
>>I just have one last hurdle to overcome, setting the bit

The main problem with just writing

 bool& operator [] ( unsigned int i);

to achieve an assibnment like

BITS_32 b;
b[1] = 0;

is that a bool& and a member of a bitfield are simply not the same - but, that bugged me, and I came up with a little trick:


struct BITS_32
{

struct _intermediate {

   _intermediate ( BITS_32* pb, unsigned int i) : m_i ( i), m_pb ( pb) {};

   void operator = ( bool b) {

     m_pb->set_bit ( m_i, b);
   }

   operator bool () const { return m_pb->get_bit ( m_i);}

   unsigned int m_i;
   BITS_32* m_pb;
 };



 unsigned long bit0 : 1;
 unsigned long bit1 : 1;
 // ...
 unsigned long bit31 : 1;

 bool get_bit ( unsigned int i) {

  switch ( i) {

  case 0: return bit0;
     break;

  case 1: return bit1;
     break;
  // ...
  }
 }

 void set_bit ( unsigned int i, bool b) {

  switch ( i) {

  case 0:  bit0 = b;
     break;

  case 1:  bit1 = b;
     break;
  // ...
  }
 }

 _intermediate operator [] ( unsigned int i) {

  return _intermediate ( this, i);
 }

};


void main () {

BITS_32 b;

b[1] = 0;

printf ( "b:%d\n", ( bool) b[1]);

b[1] = 1;

printf ( "b:%d\n", ( bool) b[1]);

}

The only "ugly" thing is to have to use the "bool" cast...
0
 
LVL 86

Expert Comment

by:jkr
ID: 7176151
Hmm, technically speaking, you could call/rename "_intermediate" a "BITS_32_BITREF" :o)
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 7176223
jkr: "a bool& and a member of a bitfield are simply not the same"

Yes, they are, if the members of the bitfield are unsigned and 1 bit wide. So returning a bool-reference with the operator[] can be used to set/reset bits. The compiler will generate code that masks the bits accordingly. At best, that is. Like I said, bitfields are a creation that came right out of hell. Once you have had your troubles with them you will never ever again refer to macros as evil.
0
 
LVL 86

Expert Comment

by:jkr
ID: 7177209
>>returning a bool-reference with the operator[] can be
>>used to set/reset bits. The compiler will generate code
>>that masks the bits accordingly

Compile&run it - then find out where that access violation comes from :o)
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 7177465
That's why I wrote "At best, that is". Works fine with comeau -- use a non-compliant compiler and it might not. That's also why I stated previously: "bitfields are BAD".
0
 

Author Comment

by:MacLeod
ID: 7177488
Thank you for the help.  This is slightly ugly, but I'm doing something unconventional.  It just works great!!!!!  Thank you very much!

P.S. I doubled the points again for the valiant effort.
0
 
LVL 86

Expert Comment

by:jkr
ID: 7177554
Thank you! :o)
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

856 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