Thread: Need some help regarding data structures

  1. #1
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46

    Need some help regarding data structures

    Hi all!
    I need some help regarding the following problem.
    I have 6 bytes of data in the following order:
    Code:
    head             = 2 bits
    data_base[32-30] = 3 bits
    pause_bit        = 1 bit
    data_base[29-15] = 15 bits
    pause_bit        = 1 bit
    data_base[14-0]  = 15 bits
    pause_bit        = 1 bit
    data_extent      = 9 bits
    pause_bit        = 1 bit
    I want to determine the data_base data. data_base has 33 bits, allocated
    non contiguously in the six bytes.

    So far, I have tried the following type of data structures:
    Code:
    typedef struct{
      // byte 1
      unsigned char head:2;
      unsigned char data_base32-30:3;
      unsigned char pause_bit1:1;
      unsigned char data_base29_28:2;
      // byte 2
      unsigned char data_base27_20;
      // byte 3
      unsigned char data_base19_15:5;
      unsigned char pause_bit1:1;
      unsigned char data_base14_13:2;
      // byte 4
      unsigned char data_base12_5;
      // byte 5
      unsigned char data_base4_0:5;
      unsigned char pause_bit1:1;
      unsigned char data_extent8_7:2;
      // byte 6
      unsigned char data_extent6_0:7;
      unsigned char pause_bit1:1;
    }Mydata;
    
    ....
    Mydata dData;
    
    memcpy( &dData, address, sizeof(Mydata) );
    With the above code, I was hoping to get the data_base bits correctly.
    It doesnt work and I can't figure out why?
    After getting the data_base bits seperately, I plan to use << and >> operators
    to determine data_base.
    I want to know if there is an easy way to determine data_base.
    Thanks for helping.
    Mas

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by Afrinux
    It doesnt work and I can't figure out why?
    That's not much to go on.

    There are a number of things with what you posted that lead me to believe that this is not the actual code copied and pasted, but a retyping that introduced its own errors.

    Are you familiar with structure packing? OS/compiler? Into what object do you plan to contain data_base (it's too big for most longs)?

    When dealing with bits and bytes, sometimes it's just easier to deal with bits and bytes.
    Last edited by Dave_Sinkula; 01-25-2006 at 11:35 PM. Reason: Un-editing. Then "a long" to "most longs".
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    Quote Originally Posted by Dave_Sinkula
    That's not much to go on.

    There are a number of things with what you posted that lead me to believe that this is not the actual code copied and pasted, but a retyping that introduced its own errors.
    You are right in this one.
    In my original code, I didnt use unsigned char
    I wrote it like this: #define BYTE unsigned char. So the original code was like BYTE head:2; ...
    I was afraid taht if I write the code here . using BYTE , then nobody would understand the code.
    If posting the original is a must to figure out the problem, I will copy and paste it here.

    Are you familiar with structure packing? OS/compiler? Into what object do you plan to contain data_base (it's too big for most longs)?
    Actually the 32rd bit of data_base is a dummy. I will only need the data bit0-bit31.
    So you suggesting to use __pack to solve my problem? I will try it .

    When dealing with bits and bytes, sometimes it's just easier to deal with bits and bytes.
    I dont understand what you wanted to say. Anyways, I will run a search on google to find out how to deal with bits and bytes.
    Thanks for your help.
    Mas

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by Afrinux
    I dont understand what you wanted to say. Anyways, I will run a search on google to find out how to deal with bits and bytes.
    What I meant about the "bits and bytes" is that if you are already intending to use "shift and mask", then why bother with the intermediate structure?

    And there was more wrong than using your #define (which for bit-fields would be non-C89 by the way).

    The thrust of my earlier comments is that debugging paraphrased code too often leads to more confusion than answers. If you want actual code debugged, post actual code.

    And... into what object type do you intend to place the results?
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    Here is the code:
    I took it from different files. I am going to post the related part
    Code:
    #define BYTE unsigned char 
    
    //---------------------------------------------------
    
    typedef struct{
    	BYTE	zero_one		: 3;
    	BYTE	data_base_31_30	: 2;
    	BYTE	marker_bit1		: 1;
    	BYTE	data_base_29_28	: 2;// byte 1
    	BYTE	data_base_27_20	;   // byte 2
    	BYTE	data_base_19_15	: 5;
    	BYTE	marker_bit2		: 1;
    	BYTE	data_base_14_13	: 2;// byte 3
    	BYTE	data_base_12_5	;   // byte 4
    	BYTE	data_base_4_0	: 5;
    	BYTE	marker_bit3		: 1;
    	BYTE	data_extensionu	: 2;// byte 5
    	BYTE	data_extensiond	: 7;
    	BYTE	marker_bit4		: 1;
    }Data_base;
    
    
    .......
    BYTE data[4];
    
    bGetDataBase( data, pDataHeader->data_base );
    
    ........
    
    //------------------------------------------------------------
    // Function: bGetDataBase
    //-------------------------------------------------------------
    BOOL	bGetDataBase( BYTE *data, BYTE *buff )
    {
    	Data_base dBase;
    
    	memcpy( &dBase, buff, sizeof(Data_base) );
    	
    	//data[0] =  data_base first byte
    	//data[1] =  data_base second byte
    	//data[2] =  data_base third byte
    	//data[3] =  data_base fourth byte
    
    	return TRUE;
    }
    And... into what object type do you intend to place the results?
    in an array: BYTE data[4];
    Thanks in advance!
    Mas

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    You're just going to have to use bitwise operators and bit shifts to extract the data, a C bit-field structure just isn't going to cut it in the long run when extracting information from external data sources.

    Even if you manage to solve the compiler specific packing problem, by whatever use of
    #pragma pack(1)
    you can arrange, you're not going to solve the compiler dependent bit-ordering.

    Code:
    struct foo {
      unsigned char bit:1;
    }
    Some compilers allocate bits from left-to-right (so our bit is actually in the LSB of storage), and other compilers allocate from right-to-left (so our bit is actually in the MSB of storage).

  7. #7
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    You're just going to have to use bitwise operators and bit shifts to extract the data, a C bit-field structure just isn't going to cut it in the long run when extracting information from external data sources.
    Thank you Salem!
    If I understand what you are saying, using data structures is just a waste of time. It is better to use bitwise operators!?
    Mas

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    It's not a good use in this example - trying to extract data from an external source.

  9. #9
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    Quote Originally Posted by Salem
    It's not a good use in this example - trying to extract data from an external source.
    Why it is not a good example?

    I have taken a new approach:
    Code:
    //------------------------------------------------------------
    // Function: bGetDataBase
    //-------------------------------------------------------------
    BOOL	bGetDataBase( BYTE *data, BYTE *buff )
    {
    	BYTE t1, t2, t3, t4, t5;
    	BYTE d1, d2, d3, d4, d5;
    
      // take only data_base bits
        t1 = (buff[0] & 0x1B);
        t2 = (buff[1] & 0xFF);
        t3 = (buff[2] & 0xFB);
        t4 = (buff[3] & 0xFF);
        t5 = (buff[4] & 0xF8);
        
        // erase market_bits
       d1 = (t1 & 0x18) | ((t1&0x03) <<1);
       d2 = t2;
       d3 = (t3 & F8) | ((t3&0x3)<<1);
       d4 = t4;
       d5 = t5;
    
    	
    	//data[0] =  data_base first byte
    	//data[1] =  data_base second byte
    	//data[2] =  data_base third byte
    	//data[3] =  data_base fourth byte
    
    	return TRUE;
    }
    What do you think about this new approach?
    If there is another easy way to do it, please help me.
    P.S. I havent compiled the new approach yet, thanks for understanding.
    Mas

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > Why it is not a good example?
    I just told you - C bit-fields are highly non-portable.
    If you want any chance of the code working from one OS/Compiler to another, then you're going to have to pick it apart by yourself.

    > What do you think about this new approach?
    Looks good - just keep that bit of functionality encapsulated in a specific function.

  11. #11
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Interesting exercise...
    Code:
    #include <stdio.h>
    
    unsigned long foo(unsigned char *addr)
    {
       return (addr[0] & 0x18UL) << 27 | /* bits 31-30 */
              (addr[0] & 0x03UL) << 28 | /* bits 29-28 */
              (addr[1] & 0xFFUL) << 20 | /* bits 27-20 */
              (addr[2] & 0xF8UL) << 12 | /* bits 19-15 */
              (addr[2] & 0x03UL) << 13 | /* bits 14-13 */
              (addr[3] & 0xFFUL) << 5  | /* bits 12- 5 */
              (addr[4] & 0xF8UL) >> 3;   /* bits 4 - 0 */
    }
    
    int main (void)
    {
       unsigned char address[6] = {0x1B,0xFF,0xFB,0xFF,0xF8,0x00};
       printf("result = %lX\n", foo(address));
       return 0;
    } 
    
    /* my output
    result = FFFFFFFF
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  12. #12
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    Quote Originally Posted by Salem
    > What do you think about this new approach?
    Looks good - just keep that bit of functionality encapsulated in a specific function.
    Thanks, I will. I am still working on it. If I get the results right, I will be back to post the final code.
    Interesting exercise...
    Dave, yeah pretty interesting. It might solve my problem. I will try it too. If it works, I will let you know.
    Thanks both of you for your precious time.
    Mas

  13. #13
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    Quote Originally Posted by Dave_Sinkula
    Interesting exercise...
    Code:
    #include <stdio.h>
    
    unsigned long foo(unsigned char *addr)
    {
       return (addr[0] & 0x18UL) << 27 | /* bits 31-30 */
              (addr[0] & 0x03UL) << 28 | /* bits 29-28 */
              (addr[1] & 0xFFUL) << 20 | /* bits 27-20 */
              (addr[2] & 0xF8UL) << 12 | /* bits 19-15 */
              (addr[2] & 0x03UL) << 13 | /* bits 14-13 */
              (addr[3] & 0xFFUL) << 5  | /* bits 12- 5 */
              (addr[4] & 0xF8UL) >> 3;   /* bits 4 - 0 */
    }
    
    int main (void)
    {
       unsigned char address[6] = {0x1B,0xFF,0xFB,0xFF,0xF8,0x00};
       printf("result = %lX\n", foo(address));
       return 0;
    } 
    
    /* my output
    result = FFFFFFFF
    */
    1000 thanks DAVE Your code did what exactly what I wanted to do.

  14. #14
    Registered User Afrinux's Avatar
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    46
    Hi Dave!
    I have stayed the rest of my day trying to figure out how you came up with this function, but still have no clue. Maybe I need a little rest .
    I also want to use the same logic to extract data_base from a data alignment like this one:
    Code:
    head             = 4 bits
    data_base[32-30] = 3 bits
    pause_bit        = 1 bit
    data_base[29-15] = 15 bits
    pause_bit        = 1 bit
    data_base[14-0]  = 15 bits
    pause_bit        = 1 bit
    Thanks for helping.
    Mas

  15. #15
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Yeah, that's what made it interesting.

    Previously this was your format.
    Code:
    head             = 2 bits
    data_base[32-30] = 3 bits
    pause_bit        = 1 bit
    data_base[29-15] = 15 bits
    pause_bit        = 1 bit
    data_base[14-0]  = 15 bits
    pause_bit        = 1 bit
    data_extent      = 9 bits
    pause_bit        = 1 bit
    So the data bits might be represented like this.
    Code:
          Byte 0   Byte 1   Byte 2   Byte 3   Byte 4   Byte 5
         hhdAApBB CCCCCCCC DDDDDpEE FFFFFFFF GGGGGpee eeeeeeep
            ^^ ^^ ^^^^^^^^ ^^^^^ ^^ ^^^^^^^^ ^^^^^
            || || |||||||| ||||| || |||||||| |||||
           0x18||   0xFF    0xF8 ||   0xFF    0xF8
              0x03              0x03
    Okay, getting those masks was pretty easy. I did the masking of a byte from the incoming array using a byte-sized constant that was an unsigned long. That was for use with the shift later. But this first-stage result will be in the lower 8 bits.

    You want to move each of these blocks of bits to the right position in the result.
    Code:
    Bit       3322222222221111111111
    Bit       10987654321098765432109876543210
              AABBCCCCCCCCDDDDDEEFFFFFFFFGGGGG
    The values of the shift might be more normal-looking if the lsb were always at bit 0. But I skipped any right-shifting to do that, and instead just moved the remaining distance.
    Code:
    unsigned long foo(unsigned char *addr)
    {
       return (addr[0] & 0x18UL) << 27 | /* bits 31-30 */
              (addr[0] & 0x03UL) << 28 | /* bits 29-28 */
              (addr[1] & 0xFFUL) << 20 | /* bits 27-20 */
              (addr[2] & 0xF8UL) << 12 | /* bits 19-15 */
              (addr[2] & 0x03UL) << 13 | /* bits 14-13 */
              (addr[3] & 0xFFUL) << 5  | /* bits 12- 5 */
              (addr[4] & 0xF8UL) >> 3;   /* bits 4 - 0 */
    }
    For example, the first shift uses 27 instead of 30 because the bits are already 3 places to the right.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What's a good generalized data structures book?
    By indigo0086 in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 11-16-2006, 01:01 PM
  2. i need advice about data structures
    By sawer in forum C Programming
    Replies: 2
    Last Post: 04-22-2006, 03:40 AM
  3. Any Good Data Structures Books?
    By YevGenius in forum C++ Programming
    Replies: 3
    Last Post: 05-26-2004, 07:49 AM
  4. array of structures, data from file
    By nomi in forum C Programming
    Replies: 5
    Last Post: 01-11-2004, 01:42 PM
  5. Array Data Structures
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 03-27-2002, 06:52 PM