Bit Fields for Dummies - Printable Version +- Makestation (https://makestation.net) +-- Forum: Technical Arts (https://makestation.net/forumdisplay.php?fid=45) +--- Forum: Software (https://makestation.net/forumdisplay.php?fid=104) +--- Thread: Bit Fields for Dummies (/showthread.php?tid=2640) |
Bit Fields for Dummies - Lain - November 4th, 2019 I recently completed an online course on embedded applications using C. To tell you the truth, it wasn't worth the few hours I invested in it. I more or less scanned through all the material, and most of it was intro stuff I already knew about optimization, like bit masking using logical/bitwise operators, compiler optimizations, const vs. #define, etc. Nothing particularly difficult to understand as long as you have a good foundation in computer science, ie. understanding how a CPU actually works. But there was one thing that I did learn, and have wondered about before. Take some data structure for example. Using C pseudocode, we can assume something that looks like this: Code: struct { And inside that data structure, you've got a bunch of boolean values (ie. true/false) Code: struct { Well, note how in this specific use-case, I have eight values in this one structure. Now, Boolean values are either 0 or 1 traditionally, so how large is this data structure? Well, 0/1 imply bits, so you might think 8 bits, or one byte. Wrong. In C, by default, a boolean value takes up one byte minimum, and since most other primitive data types (ie. int, double/float, char, etc.) can also be larger than one byte, we can say that the size can be much greater. So the data structure given above isn't one byte, but it's eight bytes. Now, this distresses me. If they're bools, they should only technically be 0 or 1 (or 0 and not 0) so we should be able to cut program size costs from an extra eight bytes to a single byte if we were to modify/read individual bit values. And sure enough, you can mask/read/write bit values pretty easily, if you used a macro function like this: Code: #define MASK(x) (1<<x) But as you can see, using macro functions everywhere can start to make things really unclear, especially when you start to combine them. Instead, in this course, they covered a cool concept called a 'bit field' which does exactly this, but without the messy code. Let's go back to our first struct of bools. Instead, we'll rewrite it: Code: struct { So the format is slightly familiar yet still different. Code: type Name : bitSize; Realistically, any type can be used here, but I'm using single-byte ints for the sake of looking cool. What's important is the colon and size of the value in bits. Yes, you can have more than one, say three bits, and so when that field is read, you may have a value from 0-7 (or a three-bit value, 2^3) Now, we can take another step further. What if you want to set/read a single bit rather than a specified group that you already made in the struct? Well, you mush them all together. To do that, we use a union (or a structure that is split up and shares memory.) Code: union{ So in short, that's how you turn a structure of eight bytes into a structure of eight bits instead, without making the code completely unreadable. It feels a little more object oriented this way, but overall, it's pretty well optimized. |