C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 08-10-2008, 01:54 PM   #1
Registered User
 
Join Date: Aug 2008
Posts: 5
Lightbulb Selecting bits with Unions.... Not working; please help!!

Hi, I'm struggling with selecting bits using structures inside unions.

I'm trying to convert an array of integers into a format suited to output on various chip pins.

As it stands, I have 8 integers that I want to output to a number of demultiplexer ICs. Each IC requires a 3-bit input. These inputs need to come from a chip with 3 8-bit outputs. The problem therefore is that I need to convert these ints to 3-bit format, string them together to form a 24-bit long word, and then cut that word into 8-bit long chunks for output.

This is what I've got so far, but as you can see, the bits don't seem to only partially reflect the correct values. Any idea what's wrong?

http://sharebee.com/4c6bd1d8 <-- .c file

Any help would be greatly appreciated!
======================================...
Code:
#include <stdio.h>
#include <stdlib.h>

int main()
{

int short x;
unsigned short led[8] = {1,1,1,1,1,1,1,1};


// PRINTS INTEGER ARRAY
printf("\nLed int array\n========================\n");
for (x=0;x<=7;x++) printf("Led %d = %d\n",x,led[x]);
printf("\n");

// UNION OF 3-BIT NUMBERS AND INDIVIDUAL BITS
union {
struct mini_words //24 bytes?
{
unsigned short a:3;
unsigned short b:3;
unsigned short c:3;
unsigned short d:3;
unsigned short e:3;
unsigned short f:3;
unsigned short g:3;
unsigned short h:3;
} word;

struct bytes
{
unsigned char b0:1;
unsigned char b1:1;
unsigned char b2:1;
unsigned char b3:1;
unsigned char b4:1;
unsigned char b5:1;
unsigned char b6:1;
unsigned char b7:1;
unsigned char b8:1;
unsigned char b9:1;
unsigned char b10:1;
unsigned char b11:1;
unsigned char b12:1;
unsigned char b13:1;
unsigned char b14:1;
unsigned char b15:1;
unsigned char b16:1;
unsigned char b17:1;
unsigned char b18:1;
unsigned char b19:1;
unsigned char b20:1;
unsigned char b21:1;
unsigned char b22:1;
unsigned char b23:1;
unsigned char b24:1;
} b;
} un;




// FILLING STRUCTURE WITH DATA FROM ARRAY
un.word.a=(led[0]);
un.word.b=(led[1]);
un.word.c=(led[2]);
un.word.d=(led[3]);
un.word.e=(led[4]);
un.word.f=(led[5]);
un.word.g=(led[6]);
un.word.h=(led[7]);

// PRINTING CURRENT STATE OF 3-BIT WORDS IN UNION
printf("Assignments to structure\n========================\n");
printf(" %hd ",un.word.a);
printf("%hd ",un.word.b);
printf("%hd ",un.word.c);
printf("%hd ",un.word.d);
printf("%hd ",un.word.e);
printf("%hd ",un.word.f);
printf("%hd ",un.word.g);
printf("%hd\n\n",un.word.h);



printf("Bits in string\n========================\n");
printf("%d",un.b.b0);
printf("%d",un.b.b1);
printf("%d ",un.b.b2);
printf("%d",un.b.b3);
printf("%d",un.b.b4);
printf("%d ",un.b.b5);
printf("%d",un.b.b6);
printf("%d",un.b.b7);
printf("%d ",un.b.b8);
printf("%d",un.b.b9);
printf("%d",un.b.b10);
printf("%d ",un.b.b11);
printf("%d",un.b.b12);
printf("%d",un.b.b13);
printf("%d ",un.b.b14);
printf("%d",un.b.b15);
printf("%d",un.b.b16);
printf("%d ",un.b.b17);
printf("%d",un.b.b18);
printf("%d",un.b.b19);
printf("%d ",un.b.b20);
printf("%d",un.b.b21);
printf("%d",un.b.b22);
printf("%d",un.b.b23);

getch();

return(0);
}
Attached Files
File Type: c qn.c (3.7 KB, 34 views)
dan56965 is offline   Reply With Quote
Old 08-10-2008, 02:15 PM   #2
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,662
Try printing out the size of your 'word' struct.
My guess is that it isn't 3 (like you're expecting).

> unsigned short e:3;
> unsigned short f:3;
Up to e, you've used 15 bits (bits 0 to 14).
But it might be down to the implementation whether the first bit of f ends up in bit 15 (what you want), or bit 16 (the start of the next storage unit, and not what you want).

Declaring them as "unsigned long" may (repeat MAY) give the compiler a clue to use a 32-bit underlying storage unit, but it's anyones guess as to whether it will work.

http://c-faq.com/struct/bitfields.html
If you're trying to map bits in hardware, then bit-fields are not the answer.
Sooner or later, you'll come unstuck.

Unfortunately, in this case, doing all the bit-bashing yourself is the only way of getting a consistent good answer.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.

Salem is offline   Reply With Quote
Old 08-10-2008, 02:21 PM   #3
Registered User
 
Join Date: Jul 2008
Posts: 133
But this mapping can't work, can it? I mean 8 shorts (16 bytes) into 24 bytes like that... How would you set 3rd byte from a, b, c... exept using b member?
EDIT: I may be wrong, but you define word.a as short, being long 3 bytes, but by using normal assignment (un.word.a=...), compiler will treat it as normal short so it will set only 2 bytes of word.a, 3rd you can access only with un.b.b2 or pointer (but it remains unset in this prog).

Last edited by rasta_freak; 08-10-2008 at 02:28 PM.
rasta_freak is offline   Reply With Quote
Old 08-10-2008, 02:31 PM   #4
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
It took me a few minutes to figure out what the problem was.
3 bits don't make even sets of 16 bits. Unsigned short is a 16-bit integer. Since bitfields do not cross the natural boundary of their constituent base-type, when you have filled 15 bits, the next bit gets padded out.

If you change your unsigned short to unsigned long [or "unsigned int" if you use a compiler which has 32-bit integers], then your results will be what I think you expect.

Note: I took too long, Salem already answered it... ;-)

--
Mats
__________________
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
matsp is offline   Reply With Quote
Old 08-10-2008, 02:40 PM   #5
Registered User
 
Join Date: Jul 2008
Posts: 133
Can anyone please direct me to some docs where this syntax is explained? I've never used it. Like what exactly is the difference between short:3 & int:3 if they are all 3 bits?
rasta_freak is offline   Reply With Quote
Old 08-10-2008, 02:44 PM   #6
Registered User
 
Join Date: Aug 2008
Posts: 5
Salem, Matsp - Thanks for the replies guys... you've been a great help.

Defining as long seems to fix it, athough based on what you've said, I'll have a stab at doing it the bit manipulation method instead.

That is, unless you're think it'll work on GCC?
dan56965 is offline   Reply With Quote
Old 08-10-2008, 02:48 PM   #7
and the Hat of Guessing
 
tabstop's Avatar
 
Join Date: Nov 2007
Posts: 8,803
Quote:
Originally Posted by C99, section 6.7.2.1
9 A bit-field is interpreted as a signed or unsigned integer type consisting of the specified
number of bits.104) If the value 0 or 1 is stored into a nonzero-width bit-field of type
_Bool, the value of the bit-field shall compare equal to the value stored.
10 An implementation may allocate any addressable storage unit large enough to hold a bitfield.
If enough space remains, a bit-field that immediately follows another bit-field in a
structure shall be packed into adjacent bits of the same unit. If insufficient space remains,
whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is
implementation-defined. The order of allocation of bit-fields within a unit (high-order to
low-order or low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified.
The difference between short:3 and int:3 being, where is the boundary, as that determines how many bitfields you can portably get inside one variable.

Edit: Footnote 104 says that if you use plain int, you get signed or unsigned int at your compiler's discretion.
tabstop is online now   Reply With Quote
Old 08-10-2008, 02:51 PM   #8
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
Quote:
Originally Posted by rasta_freak View Post
Can anyone please direct me to some docs where this syntax is explained? I've never used it. Like what exactly is the difference between short:3 & int:3 if they are all 3 bits?
Here's one page that describes the syntax.
http://www.cs.cf.ac.uk/Dave/C/node13.html

Basicly, int x:3 is the same as short x:3 in all aspects except where short and int are differnet size and you have sufficinet sets of 3 bit values to go beyond the number of bits of a short.

If we take the generic (C++ style) form:
Code:
T x:n;
T y:n;
then if bits in T is less than 2n, then they will be stored in the same T memory space. n must not be larger than the number of bits in T. So a char can only hold 8 bits [in commonl systems], an int can hold at least 16 bits in common systems and 32 bits in modern common systems. "long long int" could hold 64 bits.

However, I should point out that there's no obligation to the compiler to actually store x and y in the above example in one T unit, even if T is more bits than 2n. It could just make two T size locations and store each field in one T unit each. The only guarantee is that the value stored will be masked to match the number of bits you have choosen.

--
Mats
__________________
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
matsp is offline   Reply With Quote
Old 08-10-2008, 02:57 PM   #9
Registered User
 
Join Date: Jul 2008
Posts: 133
Salem, Matsp - - Thanks from me too
EDIT: Ooops, meant Tabstop too..

Last edited by rasta_freak; 08-10-2008 at 03:18 PM.
rasta_freak is offline   Reply With Quote
Old 08-11-2008, 04:06 AM   #10
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
Quote:
Originally Posted by dan56965 View Post
Salem, Matsp - Thanks for the replies guys... you've been a great help.

Defining as long seems to fix it, athough based on what you've said, I'll have a stab at doing it the bit manipulation method instead.

That is, unless you're think it'll work on GCC?
gcc should work OK with the "long" variety.

Edit: If you are using gcc, then I would actually recommend using "int" instead of "long" - the reason being that if you ever switch to a system that uses 64-bit "long", you'd get unexpected changes versus a system where you have 32-bit "long" values.

--
Mats
__________________
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.

Last edited by matsp; 08-11-2008 at 04:12 AM.
matsp is offline   Reply With Quote
Old 08-11-2008, 05:38 PM   #11
Registered User
 
Join Date: Aug 2008
Posts: 5
Hey, just thought I'd add this for the sake of future searchers....

I read about adding undeclared bits in a bit-field, to allow for limited container size.

This now works for me without resorting to using long or int variables:

Code:
      union {
                   struct byte_values
                   {
                          unsigned char b0:1;
                          unsigned char b1:1;
                          unsigned char b2:1;
                          unsigned char b3:1;
                          unsigned char b4:1;
                          unsigned char b5:1;
                          unsigned char b6:1;  
                          unsigned char b7:1;
                          unsigned char b8:1;
                          unsigned char b9:1;
                          unsigned char b10:1;
                          unsigned char b11:1;
                          unsigned char b12:1;
                          unsigned char b13:1;
                          unsigned char b14:1;
                          unsigned :1;        
                          unsigned char b15:1;
                          unsigned char b16:1;
                          unsigned char b17:1;
                          unsigned char b18:1;
                          unsigned :8;
                          unsigned char b19:1;
                          unsigned char b20:1;
                          unsigned char b21:1;
                          unsigned char b22:1;
                          unsigned char b23:1;          
                          unsigned char b24:1;
                          unsigned char b25:1;
                          unsigned char b26:1;
                          unsigned char b27:1;
                          unsigned char b28:1;
                          unsigned char b29:1;
                          unsigned char b30:1;
                          unsigned char b31:1;  
                          unsigned char b32:1;

 
                   } b;    
            
                   struct mini_words //24 bits?
                   {
                          unsigned short a:3;
                          unsigned short b:3;
                          unsigned short c:3;
                          unsigned short d:3;
                          unsigned short e:3;
                          unsigned short f:3;
                          unsigned short g:3;
                          unsigned short h:3;
                          unsigned int y_control:8;
                   } word;

            } un;
Thanks again everyone.
dan56965 is offline   Reply With Quote
Old 08-11-2008, 05:59 PM   #12
Registered User
 
Join Date: Aug 2008
Posts: 5
damn, posted the wrong thing there... it should have read like this:



Code:
      union {
                   struct byte_values
                   {
                          unsigned char b0:1;
                          unsigned char b1:1;
                          unsigned char b2:1;
                          unsigned char b3:1;
                          unsigned char b4:1;
                          unsigned char b5:1;
                          unsigned char b6:1;  
                          unsigned char b7:1;
                          unsigned char b8:1;
                          unsigned char b9:1;
                          unsigned char b10:1;
                          unsigned char b11:1;
                          unsigned char b12:1;
                          unsigned char b13:1;
                          unsigned char b14:1;
                          unsigned :1;
                          unsigned char b15:1;
                          unsigned char b16:1;
                          unsigned char b17:1;
                          unsigned char b18:1;
                          unsigned char b19:1;
                          unsigned char b20:1;
                          unsigned char b21:1;
                          unsigned char b22:1;
                          unsigned char b23:1;          
                          unsigned :1;
                          unsigned char b24:1;
                          unsigned char b25:1;
                          unsigned char b26:1;
                          unsigned char b27:1;
                          unsigned char b28:1;
                          unsigned char b29:1;
                          unsigned char b30:1;
                          unsigned char b31:1;  

 
                   } b;    
            
                   struct mini_words //24 bits?
                   {
                          unsigned short a:3;
                          unsigned short b:3;
                          unsigned short c:3;
                          unsigned short d:3;
                          unsigned short e:3;
                          unsigned short f:3;
                          unsigned short g:3;
                          unsigned short h:3;    
                          unsigned int y_control:8;
                   } word;
                   

            } un;
dan56965 is offline   Reply With Quote
Old 08-11-2008, 11:02 PM   #13
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,662
Saying
unsigned short a:3;
is no different to
unsigned long a:3;
it's still only 3 bits.

> it should have read like this:
Really?
Because struct byte_values contains 34 bits.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.

Salem is offline   Reply With Quote
Reply

Tags
bits, structures, unions

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Bitwise Operators.... o0obruceleeo0o C++ Programming 21 04-09-2003 06:45 AM
what is the significance of low order and high order bits Shadow12345 Windows Programming 1 11-16-2002 11:46 AM
copy some bits into a 8 bits binary number Unregistered C Programming 6 05-29-2002 10:54 AM
opengl code not working Unregistered Windows Programming 4 02-14-2002 10:01 PM
Help Please...bits Unregistered C Programming 11 01-24-2002 01:43 PM


All times are GMT -6. The time now is 06:12 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22