You are here:

C++/what is the difference between this two?

Advertisement


Question
Hello,

please, here is a working code that displays the binary bit pattern, byte by byte using a union.

code:

#include <iostream>

#define SIZE     3

using namespace std;

union bits{
     bits(double n);
     void show_bits();
     int d;
     unsigned char c[SIZE];
     };
     
     bits::bits(double n){
     d = n;
     }
     void bits::show_bits(){
         int i, j;
         for(j=SIZE-1; j>=0; j--)
         {
         cout <<"bit pattern in byte" << j<<":";
         for(i=128;i;i>>=1)
         if(i&c[j])cout << "1";
         else cout << "0";
         cout<<"\n";
         }
         }
         int main(){
         bits ob(20);
         ob.show_bits();
         
         return 0;
         }

but when i modify the union to a class like this:

class bits{
     bits(double n);
     void show_bits();
     
     private:
     int d;
     unsigned char c[SIZE];
     };

the code still works but doesnt display the real bits in the number 20..

what could be the problem?  

Answer
The answer is almost certainly due to a fundamental difference between union types and struct or class types.

I am also a bit confused why both the union and class versions of bits store member d as an int but initialise them in the constructor from a double value - that seems decidedly iffy to me.

Further I do not see how the code presented for the class version ever compiled as the constructor and show_bits member functions are _private_ - the default for classes.

OK so putting these points aside let us review unions vs. classes and structs.

All the members in a union _share_ the same memory - they all start at the same offset - an offset of zero from the start of a union instance. A union instance has a size large enough to store the largest member. Hence the bits of d share the memory with the bits of the unsigned chars in the c array member - in fact there are probably _more_ bits in the d member as ints are most commonly 32-bits in size on popular desktop and server operating systems, and you only store 3 unsigned chars, which are almost certainly 8-bits in size, making c only 24 bits in size - hence d will be the largest member. This would not be true if say you were using a 16-bit compiler.

On the other hand the members in struct and class types are laid out one after another in memory and occupy _separate_ memory locations. The size of a class or struct instance is at least as large as the _sum_ of the sizes of all the data members. Hence when you write data into d in the class version of bits you _do_ _not_ _alter_ the c instance member; the c instance member is _separate_ from the d instance member.

The solution is to wrap the class data members in an anonymous union, thus:

   class bits
   {
   public:
       bits(double n);
       void show_bits();
         
   private:
       union
       {
         int d;
         unsigned char c[SIZE];
       };
   };

That will solve your immediate problem. However I am not really sure why you require a union at all, for example you could write a function something like so:

   #include <limits>

   void ShowBits( unsigned int n )
   {
     typedef std::numeric_limits<unsigned int> uint_limits;
     unsigned int bit(uint_limits::max()&~(uint_limits::max()>>1));
     unsigned int  const BitsPerByte(8);
     unsigned int bit_num = uint_limits::digits;
     do
     {
       if (0==bit_num%BitsPerByte)
       {
         if (bit_num < uint_limits::digits)
         {
         std::cout << '\n';
         }
         std::cout << "Bit pattern in byte " << bit_num/BitsPerByte-1 << " : ";
       }
       std::cout << ((bit&n) ? '1' : '0');
       --bit_num;
     }
     while( (bit>>=1) != 0 );
     std::cout << std::endl;
   }

Which is not an exact replica of your functionality as it shows _all_ bits in _all_ bytes of an unsigned int. A version taking int could easily be provided as an overload:

   void ShowBits( int n )
   {
       return ShowBits( static_cast<unsigned int>(n) );
   }

And we can test each in main thus:

   int main()
   {
      ShowBits(20u);
      std::cout << "\n----------------------------------------------\n\n";
      ShowBits(-20);
      return 0;
   }

The u after 20 indicates we mean an unsigned int literal rather than an int literal.

Hope you find this of use.

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.