Thread: Bit Fields

  1. #1
    Registered User
    Join Date
    Apr 2017
    Posts
    7

    Bit Fields

    I am having trouble printing the dates from a binary file. Here is the table that I am using for reference:
    Bit Fields-screen-shot-2019-02-23-12-45-18-pm-png

    Here is my code:
    Code:
    #include <stdio.h>
    
    
    struct MiscBits
    {
        unsigned id: 2;
        unsigned category: 2;
        unsigned engaged : 1;
        unsigned reserved: 3;
    };
    
    
    struct Date {
    
    
        unsigned year: 7;
        unsigned month: 4;
        unsigned day: 5;
    
    
        unsigned hour: 5;
        unsigned minute: 6;
        unsigned reserved2: 5;
    
    
        unsigned second: 6;
        unsigned reserved3: 10;
    };
    
    
    struct Record {
        float latitude;
        float longitude;
        short altitude;
        char name[5];
        struct MiscBits Misc;
        char Reported[6];
        struct Date myDate;
    } __attribute__((packed));
    
    
    
    
    int main(){
    
    
        FILE *file;
        struct Record myRecord;
        file = fopen("tracks2.dat", "rb");
    
    
        for(int i=0;i<4;i++) {
            fread(&myRecord,22,1,file);
            printf("latitude: %f longitude: %f altitude: %d name: %s ", myRecord.latitude,myRecord.longitude,myRecord.altitude,myRecord.name);
            
            printf("%d %d %d %d %d %d %d %d", myRecord.myDate.year, myRecord.myDate.month, myRecord.myDate.day, myRecord.myDate.hour, myRecord.myDate.minute, myRecord.myDate.second);
            switch (myRecord.Misc.id) {
                case 0: printf("%s ", "ID: Uknown");
                    break;
                case 1: printf("%s ", "ID: Friend");
                    break;
                case 2: printf("%s ", "ID: Foe");
                    break;
                case 3: printf("%s ", "ID: Neutral");
                    break;
            }
            switch (myRecord.Misc.category) {
                case 0: printf("%s ", "Category: Ship");
                    break;
                case 1: printf("%s ", "Category: Ground vehicle");
                    break;
                case 2: printf("%s ", "Category: Airplane");
                    break;
            }
            switch (myRecord.Misc.engaged){
                case 0: printf("%s\n ", "Not Engaged");
                    break;
                case 1: printf("%s\n ", "Engaged");
                    break;
            }
        }
        fclose(file);
        return(0);
    }
    My program prints the other structs out correctly but not the date struct.

  2. #2
    Registered User
    Join Date
    Apr 2017
    Posts
    7
    Update: I removed line 37 and moved line 56 to after all the switch statements but still incorrect output.

  3. #3
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    Try
    Code:
    fread(&myRecord, sizeof myRecord, 1, file);
    A little inaccuracy saves tons of explanation. - H.H. Munro

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    You could also try reading the file more carefully, a field at a time, and extracting the bits manually.
    This is totally untested so you may need to fix some things.
    Code:
    #include <stdint.h>    // compile as -std=c99
     
    float latitude, longitude;
    uint16_t altitude;
     
    fread(&latitude,  sizeof latitude,  1, file);
    fread(&longitude, sizeof longitude, 1, file);
    fread(&altitude,  sizeof altitude,  1, file);    // print like printf("%d\n", (int)altitude);
     
    char name[6];
    fread(name, sizeof name - 1, 1, file);
    name[sizeof name - 1] = '\0';
     
    uint8_t b0;
    fread(&b0, sizeof b0, 1, file);
     
    int id       =  b0       & 0x03;
    int category = (b0 >> 2) & 0x03;
    int engaged  = (b0 >> 4) & 0x01;
    int res1     = (b0 >> 5);
     
    char reported[7];
    fread(reported, sizeof reported - 1, 1, file);
    name[sizeof reported - 1] = '\0';
     
    uint16_t w0, w1, w2;
    fread(&w0, sizeof w0, 1, file);
    fread(&w1, sizeof w1, 1, file);
    fread(&w2, sizeof w2, 1, file);
     
    int year   =  w0        & 0x7f;
    int month  = (w0 >>  7) & 0x0f;
    int day    = (w0 >> 11);
    int hour   =  w1        & 0x1f;
    int minute = (w1 >>  5) & 0x3f;
    int res2   = (w1 >> 11);
    int second =  w2        & 0x3f;
    int res3   = (w2 >>  6);
    It's also possible that w0, w1, and w2 should be read in the opposite order:
    Code:
    fread(&w2, sizeof w2, 1, file);
    fread(&w1, sizeof w1, 1, file);
    fread(&w0, sizeof w0, 1, file);
    Last edited by john.c; 02-24-2019 at 08:28 PM.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User
    Join Date
    Apr 2017
    Posts
    7
    The first assignment/task was to extract the bits manually. I have to use bit fields now to extract the memory. And I know the size of the record, so I don't think I need the sizeof function.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Marcusrogers23
    And I know the size of the record, so I don't think I need the sizeof function.
    You should still use sizeof instead of hardcoding a magic number.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Apr 2017
    Posts
    7
    hahah, thank you for taking the time to try and help though!

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > I have to use bit fields now to extract the memory.
    The ordering of bitfields is implementation defined.

    Code:
    struct foo {
        int field : 6;
    };
    Assume for the moment that the allocated storage unit is a short int (for clarity).
    There is nothing in the standard which says that you would end up with these bits.
    ???????? ??xxxxxx

    It is also perfectly acceptable for your compiler to choose to do this.
    xxxxxx?? ????????

    Having read a date, you could try this bit of debugging to see if your date bits make any sense just after reading them in.
    Code:
    unsigned short foo[3];  // same size as Date
    memcpy(foo,&myRecord.myDate,3);
    printf("Date Bits=%04x %04x %04x\n", foo[0],foo[1],foo[2]);
    You can then also use the same idea to explore how your bitfields are packed.
    Code:
    memset(&myRecord,0,sizeof(myRecord);
    myRecord.year = ~0;  // set all the bits for year
    memcpy(foo,&myRecord.myDate,3);
    printf("Date Bits=%04x %04x %04x\n", foo[0],foo[1],foo[2]);
    The hypothesis is that foo[0] should be 0x007f.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Bit fields and hex
    By MeNeedsHelp in forum C Programming
    Replies: 22
    Last Post: 09-27-2014, 03:44 AM
  2. Bit-Fields in C.
    By Mr.Lnx in forum C Programming
    Replies: 5
    Last Post: 06-29-2014, 07:22 AM
  3. Bit fields
    By juice in forum C Programming
    Replies: 7
    Last Post: 12-13-2011, 08:38 AM
  4. Bit fields
    By Edelweiss in forum C Programming
    Replies: 5
    Last Post: 08-23-2011, 10:01 AM
  5. Bit fields
    By Perspektyva in forum C++ Programming
    Replies: 13
    Last Post: 11-22-2008, 02:38 PM

Tags for this Thread