Hardware friendly C structures

What I really want is a language that has really good structures. That is, they can represent hardware/fixed layouts effectively.

Say I were to enhance C (instead of designing a whole new language). I want something like this:

struct FATBoot {
    uint8_t BS_jmpBoot[3];
    char BS_OEMName[8];
    little uint16_t BPB_BytsPerSec;
    uint8_t BPB_SecPerClus;
    little uint16_t BPB_RsvdSecCnt;
    uint8_t BPB_NumFATs;
    little uint16_t BPB_RootEntCnt;
    little uint16_t BPB_TotSec16;
    uint8_t BPB_Media;
    little uint16_t BPB_FATSz16;
    little uint16_t BPB_SecPerTrk;
    little uint16_t BPB_NumHeads;
    little uint32_t BPB_HiddSec;
    little uint32_t BPB_TotSec32;
    union {
        struct { // FAT12 and FAT16 only:
            uint8_t BS_DrvNum;
            uint8_t BS_Reserved1;
            uint8_t BS_BootSig;
            little uint32_t BS_VolID;
            char BS_VolLab[11];
            char BS_FilSysType[8];
        };
        struct { // FAT32 only:
            little uint32_t BPB_FATSz32;
            little uint16_t BPB_ExtFlags;
            little uint16_t BPB_FSVer;
            little uint32_t BPB_RootClus;
            little uint16_t BPB_FSInfo;
            little uint16_t BPB_BkBootSec;
            uint8_t BPB_Reserved[12];
            uint8_t BS32_DrvNum;
            uint8_t BS32_Reserved1;
            uint8_t BS32_BootSig;
            little uint32_t BS32_VolID;
            char BS32_VolLab[11];
            char BS32_FilSysType[8];
        };
    };
    align(510)
        little uint16_t BS_FATMagic;
};

I picked this structure because I was unable to represent it in my fat C code because of the crazy alignment. The only thing new yet is the “little” and “align” keywords to specify endian, and alignment/offset respectively. You would probably end up using typedefs like “luint16_t” instead of “little uint16_t”. “big”, of course, would also exist. If neither is specified, then you don’t care and therefore should be implementation defined.

Then what I want is this:

{
    tight FATBoot diskBoot;
    loose FATBoot memBoot;
    pread(fd, &diskBoot, sizeof(diskBoot), 0);
    memBoot = diskBoot;
}

memboot is the structure using the alignment and endianness of the host processor (the “loose” keyword). diskBoot is the structure packed as specified and using the endian specified. The endian would be enforced so that the memory image of diskBoot would always be correct. Accessing diskBoot.BPB_TotSec32 would evaluate to the EXACT same thing as memBoot.BPB_TotSec32 but memBoot would be quicker since it doesn’t have to reverse (potentially) or read the bytes out and reconstruct the uint16 in some odd way (because of the weird alignment of the structure). This puts a lot of extra burden on structure copies when one is loose and one is tight, so you would expect them to be slow–certainly not memcpy() speeds.

You could also use “strict” and “relaxed” but “loose” and “tight” are both 5 letters. 🙂

Basically, I want the compiler to deal with stupid endianness for me. I also want my structure to not be compiler dependant. I should be able to publish the structure in my spec and it should work on all compilers and architectures. Bit fields, for instance would be specified a certain way and not be “implementation defined”. At lease the tight ones would. Loose means “implementation defined, and fast”. Tight means “standards defined, but possibly slower”.

Leave a Reply

Your email address will not be published. Required fields are marked *