Search code examples
cstructbytebitbin

Trying to write low-level bit library, but I get an error, or garbage when trying to cast byte struct to char type


I'm trying to write functions to access individual bits in a byte, word, dword, or qword with an object-oriented style in ANSI C, but I'm not getting the results I imagine I should be. The bit type is declared like this:

typedef enum {F=0,T=1} bit;

The byte type is declared as a struct:

typedef struct {
    bit b0:1;
    bit b1:1;
    bit b2:1;
    bit b3:1;
    bit b4:1;
    bit b5:1;
    bit b6:1;
    bit b7:1;
} byte;

I then use the function makebyte to create the byte. This is defined like so:

byte makebyte(bit b7, bit b6, bit b5, bit b4, bit b3, bit b2, bit b1, bit b0){
    byte out;
    out.b0=b0;
    out.b1=b1;
    out.b2=b2;
    out.b3=b3;
    out.b4=b4;
    out.b5=b5;
    out.b6=b6;
    out.b7=b7;
    return out;
}

Then I'm trying to convert this struct to a single byte char type, like this:

char byteval(byte b){
    char *out=(char)&b;
    return out;
}

Then here I call it in my main function:

int main(int argc, char **argv){
    byte k;
    k=makebyte(0,0,1,0,0,1,0,0);
    printf("%c\n\n", byteval(k));
}

Now, my problem is that I'm basically getting garbage printed to the terminal instead of the ASCII character I'm looking for, '$'

I'm trying To Make the code Clean and Readable, since I plan on releasing it in the Public Domain. Thanks in advance!


Solution

  • I would remove all the pointer punning and convert the function to macro. I would also use union for this purpose

    typedef union 
    {
        struct 
        {
            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 uc;
    } byte;
    
    #define makebyte(b7, b6, b5, b4, b3, b2, b1, b0) \
        (byte){b0,b1,b2,b3,b4,b5,b6,b7}
    
    int main(int argc, char **argv){
        byte k;
        k=makebyte(0,0,1,0,0,1,0,0);
        printf("%c\n\n", k.uc);
    }
    

    https://godbolt.org/z/8WEezYdWa

    You need to know that standard does not define order of bits in the bitfield struct. gcc is consistent and does it your way.