Presentation is loading. Please wait.

Presentation is loading. Please wait.

Manipulating Bit Fields in C

Similar presentations


Presentation on theme: "Manipulating Bit Fields in C"— Presentation transcript:

1 Manipulating Bit Fields in C
COMP 40: Machine Structure and Assembly Language Programming (Fall 2016) Manipulating Bit Fields in C Noah Mendelsohn Tufts University Web:

2 Goals for this presentation
Learn to use C language to pack and extract bit fields Also: learn exact width C integer types

3 Warning: Because it makes the examples easier to understand, some of the code in these slides uses the syntax: 0b for literals. This is a GNU extension to the C language that is not allowed in COMP 40 code. You may use hex literals like this: 0xC9 as they are standard.

4 Exact Width Integer Types

5 Why exact width integer types?
The problem: C integer types aren’t fixed size Size of char, int, long, etc. depends on platform and compiler Sometimes we need to get a known size The solution: stdint.h defines fixed size integers int32_t: 32 bit signed integer uint32_t: 32 bit unsigned integer int16_t: 16 bit signed integer uint64_t: 64 bit unsigned integer Etc. When writing bit packing code, you need to know or account for the size of the integers you’re manipulating

6 Why Bother with Bit Fields?

7 Why use bit fields? Save space:
Storing 10 million values each ranging from 0-10 If each is a 32 bit int: 40 megabytes If each is a 4 bit int: 5 megabytes Manipulate standard file formats and network packets Sometimes, you have to (write flags into a device register)

8 Example: Internet Protocol Packet
How can we extract this 8 bit protocol number from the 32 bit field? Example: Internet Protocol Packet 32 bits V HDLN SVC TYPE LENGTH ID FLGS FRAG OFFSET TTL PROTOCOL HDR CHECKSUM SOURCE ADDRESS DESTINATION ADDRESS OPTIONS THE TCP OR UDP DATA (VARIABLE LEN)

9 Extracting Bit Fields

10 Extracting a bit field * * Note that extra spaces have been used in these boolean literals to make them, easier to read. Such spaces are not allowed in code (and, as previously noted, the 0b1001 syntax is a GNU extension not allowed in COMP 40 submissions anyway). uint16_t i = 0b ;

11 Extracting a bit field “and” together i and mask
Create mask to select bits we need Extracting a bit field uint16_t i = 0b ; uint16_t mask = 0b ; “and” together i and mask (i & mask) == 0b ;

12 Extracting a bit field “and” together i and mask?
uint16_t i = 0b ; uint16_t mask = 0b ; “and” together i and mask? (i & mask) == 0b ; … and shift to finish the job (i & mask) >> 5 == 0b ;

13 Be careful with signed shifts
uint16_t u = 0b ; int16_t i = 0b ; uint16_t mask = 0b ; In this example, masking leaves on high order bit (u &= mask) == 0b ; (i &= mask) == 0b ; Signed shifts usually propagate that bit! u >> 13 == 0b ; i >> 13 == 0b ;

14 Be careful with signed shifts
uint16_t u = 0b ; int16_t i = 0b ; uint16_t mask = 0b ; Unsigned is correct Signed has unwanted leading 1’s In this example, masking leaves on high order bit (u &= mask) == 0b ; (i &= mask) == 0b ; Signed shifts usually propagate that bit! u >> 13 == 0b ; i >> 13 == 0b ;

15 Be careful with signed shifts
Huh? Be careful with signed shifts Turns out that right shifting of a signed integer is implementation define…but why? C wants these operations to be super-efficient, and on some hardware there’s no efficient signed shift. On our systems, the sign will propagate and you may count on that in your homework submissions. uint16_t u = 0b ; int16_t i = 0b ; uint16_t mask = 0b ; In this example, masking leaves on high order bit u &= mask: 0b ; i &= mask == 0b ; Signed shifts usually propagate that bit! u >> 13 == 0b ; i >> 13 == 0b ;

16 How can we choose the bits to extract at runtime?
unsigned short i = 0b ; int width = 3; int offset = 5; This time we’ll have to compute the mask unsigned short mask = ~0; /* mask is now */ /* mask is now */ mask = mask >> (16 - width) << (offset); (i & mask) >> offset == 0b ; Now, finish the job as before

17 We can adapt to integer size at runtime
unsigned short i = 0b ; int width = 3; int offset = 5; This time we’ll have to compute the mask unsigned short mask = ~0; /* mask is now */ /* mask is now */ mask = mask >> (number_of_bits - width) << (offset); (i & mask) >> offset == 0b ; Now, finish the job as before const number_of_bits = sizeof(unsigned short) * 8;

18 Setting Bit Fields

19 Putting new value in a bit field
uint16_t i = 0b ; uint16_t new_value = 0b 0 1 0; /* value we want * uint16_t mask = 0b ; “and” together i and mask (i & mask) == 0b ;

20 Putting new value in a bit field
Important: we have zeros where new value is going Putting new value in a bit field uint16_t i = 0b ; uint16_t new_value = 0b 0 1 0; /* value we want * uint16_t mask = 0b ; “and” together i and mask… (i & mask) == 0b ;

21 Putting new value in a bit field
uint16_t i = 0b ; uint16_t new_value = 0b 0 1 0; /* value we want * uint16_t mask = 0b ; “and” together i and mask… (i & mask) == 0b ; … shift the new value and use “or” to combine ((i & mask)| (new_value << 5)) == 0b ;

22 Flag Bits

23 Very common idiom – single bit flags
One bit each /* Flag definitions */ const uint16_t HI_PRIORITY = 0x8000; const uint16_t SECURE = x4000; const uint16_t ARCHIVED = 0x2000; const uint16_t BEAUTIFUL = 0x0002; const uint16_t SPECTACULAR = 0x0001;

24 Very common idiom – single bit flags
Can use binary instead of hex, but hard to count the zeros! Very common idiom – single bit flags /* Flag definitions */ const uint16_t HI_PRIORITY = 0b ; const uint16_t SECURE = b ; const uint16_t ARCHIVED = 0b ; const uint16_t BEAUTIFUL = 0b ; const uint16_t SPECTACULAR = 0b ;

25 Initializing flags Use | to combine bits /* Flag definitions */
const uint16_t HI_PRIORITY = 0b ; const uint16_t SECURE = b ; const uint16_t ARCHIVED = 0b ; const uint16_t BEAUTIFUL = 0b ; const uint16_t SPECTACULAR = 0b ; uint16_t myflags = SECURE | BEAUTIFUL; /* secure and beautiful */

26 Test flags with &  remember C treats anything != 0 as true!
Testing flags /* Flag definitions */ const uint16_t HI_PRIORITY = 0b ; const uint16_t SECURE = b ; const uint16_t ARCHIVED = 0b ; const uint16_t BEAUTIFUL = 0b ; const uint16_t SPECTACULAR = 0b ; if (myflags & BEAUTIFUL) {…}; /* if beautiful */

27 Testing multiple flags on
Testing flags Testing multiple flags on /* Flag definitions */ const uint16_t HI_PRIORITY = 0b ; const uint16_t SECURE = b ; const uint16_t ARCHIVED = 0b ; const uint16_t BEAUTIFUL = 0b ; const uint16_t SPECTACULAR = 0b ; if ((myflags & (BEAUTIFUL | SECURE)) == (BEAUTIFUL | SECURE)) {…}; /* if beautiful and secure */

28 Us | to turn on additional flags
Turning flags on /* Flag definitions */ const uint16_t HI_PRIORITY = 0b ; const uint16_t SECURE = b ; const uint16_t ARCHIVED = 0b ; const uint16_t BEAUTIFUL = 0b ; const uint16_t SPECTACULAR = 0b ; myflags |= ARCHIVED; /* now it’s archived too */

29 To turn off, & with all the other flags!
Turning flags off /* Flag definitions */ const uint16_t HI_PRIORITY = 0b ; const uint16_t SECURE = b ; const uint16_t ARCHIVED = 0b ; const uint16_t BEAUTIFUL = 0b ; const uint16_t SPECTACULAR = 0b ; myflags &= ~BEAUTIFUL; /* but not beautiful anymore  */


Download ppt "Manipulating Bit Fields in C"

Similar presentations


Ads by Google