Passing a byte and its bits to a function

This is a discussion on Passing a byte and its bits to a function within the C Programming forums, part of the General Programming Boards category; Is there a way to pass a union member into a function? For instance, I have a function prototype here: ...

  1. #1
    Registered User
    Join Date
    Dec 2008
    Posts
    2

    Passing a byte and its bits to a function

    Is there a way to pass a union member into a function? For instance, I have a function prototype here:
    Code:
     
    Void function(unsigned char input);
    Now, I want to pass an 8-bit variable to the function, but I want access to each individual bit within the function. Normally, I can make a union in my main function loop for a variable like so:
    Code:
    union variable {
    	unsigned char byte;
    	struct {
    	unsigned b0:1;
    	unsigned b1:1;
    	unsigned b2:1;
    	unsigned b3:1;
    	unsigned b4:1;
    	unsigned b5:1;
    	unsigned b6:1;
    	unsigned b7:1; 	
    	} bits;
    }; 
    volatile union variable var1;  //the actual union name for this specific instance is var1
    I have made a union for my unsigned char because in some operations, I want to operate on the 8 bit variable (for instance, subtract 15 from var1: var1.byte - 15), while in other operations, I want to operate on individual bits of the variable (for instance, is bit 3 of var1 equal to 0: var1.bits.b3 == 0).

    Now, concerning the definition for my function, it might look something like this:
    Code:
    Void function(unsigned char input)
    	{
    	Input.b2 = 1;
    	}
    I am passing one entire 8-bit variable to the function, but inside the function, I want to operate on the individual bits of this variable. How would I do this? I think I need a union with a structure somewhere (like I have included above), but I am not sure if this union is placed in the main loop where the passing variable is, or inside the function definition where the temporary variable to the function is, or should the variable union be declared as a global (outside of any function)?

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    So what exactly do you want to do? Change your function to take a union as argument, or pass the x.byte to the function, when x is of the union described above? Or something else?

    --
    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.

  3. #3
    Registered User
    Join Date
    Dec 2008
    Posts
    2
    Sorry about my lack of clarity!

    What I want to do is this:

    In my main loop: declare a generic 8-bit variable

    Pass this variable to a function

    Within the function, operate on individual bits of the passed variable (test these bits to see if they are equal to 1 or 0)

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Ok, I'm going to let you try it out for yourself. How do you THINK you should do 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.

  5. #5
    Registered User slingerland3g's Avatar
    Join Date
    Jan 2008
    Location
    Seattle
    Posts
    603
    With a union you can only store one or the other but not both as they share the same memory space. So are you needing to set(store) the specific bits of a passed in byte to a function within your struct definition? What the purpose of the char then? There are other ways of doing this. As I see it you will need to set your bits like so:


    variable.bits.b0 = 1;

    Or something like that.

  6. #6
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    478
    Quote Originally Posted by slingerland3g View Post
    With a union you can only store one or the other but not both as they share the same memory space. So are you needing to set(store) the specific bits of a passed in byte to a function within your struct definition? What the purpose of the char then? There are other ways of doing this. As I see it you will need to set your bits like so:


    variable.bits.b0 = 1;

    Or something like that.
    It's rather that he can store them as both, not one or the other. If you had a union with a double and an int, and you put a double such as 1.5 in it, and then retrieved the int, you would get the int whose bits and bytes are the direct equivalent to the bits and bytes of the double(At least, as much of the double as the int can store, eg. 4 bytes). If you were to cast it to an int, you'd get 1.0.

    This effectively means he can assign a whole byte to the unsigned char part of his union, and then retrieve its individual bits, as well as change them.
    "What's up, Doc?"
    "'Up' is a relative concept. It has no intrinsic value."

  7. #7
    Registered User slingerland3g's Avatar
    Join Date
    Jan 2008
    Location
    Seattle
    Posts
    603
    If I am understanding your path you are taking. Try printing both the byte variable as well as any bit assignment from your var1 Union after assigning each and let me know what you get.

  8. #8
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    I believe the best way to do this is not with bit-fields. It is with a mask and functions. Do this:
    Code:
    char getBit(unsigned char byte, char pos) //pos {1,8}
    {
        switch(pos)
        {
             case 1:
                 return byte & 1; // 00000001
             case 2:
                 return byte & 2; // 00000010
             ...
             case 8:
                 return byte & 128; // 10000000
        }
    }
    
    void setBit(unsigned char* byte, char bit, char pos) //bit = 0 or 1, pos {1,8}
    {
        if (bit == 0)
            switch(pos)
            {
             case 1:
                 *byte &= 254; // 11111110
             ...
             case 8:
             ...     
            }
        else if (bit == 1)
            switch(pos)
            {
             case 1:
                 *byte |= 1; // 00000001
             ...
             case 8:
             ...     
            } 
    }
    or sth like that. So you use an unsigned char as a byte and just access each bit with bit operators. What you do is also possible, but again, you would need to copy each time the value of byte to bits and vice versa if you want to use a struct.

    edit: I would guess that you cannot actually access 1 bit, so each bit will take 1 byte int the memory. So there is no reason to use bit fields if you also want to use the byte as whole. If the struct is actually 2 bytes in total (1 for byte, 1 for bits) then you MIGHT be able to have only the bits and cast the struct to an unsigned char, though don't think something like this will work.
    Last edited by C_ntua; 12-03-2008 at 09:54 PM.

  9. #9
    Registered User
    Join Date
    Aug 2006
    Posts
    99
    Interesting read about "optimizing" by using bit fields.

    http://blogs.msdn.com/oldnewthing/ar...6/9143050.aspx

    Not really worth the effort.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by rdrast View Post
    Interesting read about "optimizing" by using bit fields.

    http://blogs.msdn.com/oldnewthing/ar...6/9143050.aspx

    Not really worth the effort.
    But that wasn't what the original poster was talking about. (S)He wants to read and write bits out of a byte - so we have 8 tightly packed bits in a unsigned char, and we want to overlay those with the same bit pattern defined as one bit each. This requires some sort of bitwise operations to be performed by the code - there is no other way we can take 8 tightly packed bits and "deal with them".

    The linked article talks about trying to store unrelated data items AS TIGHTLY PACKED BITS, in an effort to save space. Which the article argues is a waste of effort, and I would agre (as a general rule at least - if there are thousands of booleans that can be packed tightly together, then it may well be worth 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.

Popular pages Recent additions subscribe to a feed

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