manipulating bit fields in c n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Manipulating Bit Fields in C PowerPoint Presentation
Download Presentation
Manipulating Bit Fields in C

Loading in 2 Seconds...

play fullscreen
1 / 29

Manipulating Bit Fields in C - PowerPoint PPT Presentation


  • 63 Views
  • Uploaded on

COMP 40: Machine Structure and Assembly Language Programming (Spring 2014). Manipulating Bit Fields in C. Noah Mendelsohn Tufts University Email: noah@cs.tufts.edu Web: http://www.cs.tufts.edu/~noah. Goals for this presentation. Learn to use C language to pack and extract bit fields

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Manipulating Bit Fields in C' - rian


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
manipulating bit fields in c

COMP 40: Machine Structure and

Assembly Language Programming (Spring 2014)

Manipulating Bit Fields in C

Noah Mendelsohn

Tufts UniversityEmail: noah@cs.tufts.edu

Web: http://www.cs.tufts.edu/~noah

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

Warning:

  • Because it makes the examples easier to understand, some of the code in these slides uses the syntax:0b11001001for 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.

why exact width integer types
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
why use bit fields
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
example internet protocol packet

How can we extract this 8 bit protocol number from the 32 bit field?

Example: Internet Protocol Packet

32 bits

LENGTH

SVC TYPE

V

HDLN

ID

FLGS

FRAG OFFSET

TTL

PROTOCOL

HDR CHECKSUM

SOURCE ADDRESS

DESTINATION ADDRESS

OPTIONS

THE TCP OR UDP DATA (VARIABLE LEN)

extracting a bit field
Extracting a bit field

*

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;

* 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).

extracting a bit field1

Create maskto select bits we need

Extracting a bit field

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t mask = 0b 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0;

“and” together i and mask

(i & mask) == 0b 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0;

extracting a bit field2
Extracting a bit field

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t mask = 0b 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0;

“and” together i and mask?

(i & mask) == 0b 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0;

… and shift to finish the job

(i & mask) >> 5 == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;

be careful with signed shifts
Be careful with signed shifts

uint16_tu = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

int16_t i = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t mask = 0b 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

In this example, masking leaves on high order bit

(u &= mask) == 0b 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

(i &= mask) == 0b 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

Signed shifts usually propagate that bit!

u >> 13 == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;

i >> 13 == 0b 1 1 1 1 1 1 1 1 1 1 1 1 1 10 1;

be careful with signed shifts1
Be careful with signed shifts

uint16_tu = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

int16_t i = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t mask = 0b 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

Unsigned is correctSigned has unwanted leading 1’s

In this example, masking leaves on high order bit

(u &= mask) == 0b 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

(i &= mask) == 0b 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

Signed shifts usually propagate that bit!

u >> 13 == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;

i >> 13 == 0b 1 1 1 1 1 1 1 1 1 1 1 1 1 10 1;

be careful with signed shifts2

Huh?

Be careful with signed shifts

Turns out that right shifting of a signedinteger 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 willpropagate and you may count on that in your homework submissions.

uint16_tu = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

int16_t i = 0b 1 0 1 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t mask = 0b 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0;

In this example, masking leaves on high order bit

u &= mask: 0b 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1;

i &= mask == 0b 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1;

Signed shifts usually propagate that bit!

u >> 13 == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;

i >> 13 == 0b 1 1 1 1 1 1 1 1 1 1 1 1 1 10 1;

how can we choose the bits to extract at runtime
How can we choose the bits to extract at runtime?

unsigned short i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;

int width = 3; int offset = 5;

This time we’ll have to compute the mask

/* mask is now 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 */

unsigned short mask = ~0;

/* mask is now 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */

mask = mask >> (16 - width) << (offset);

Now, finish the job as before

(i & mask) >> offset == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;

we can adapt to integer size at runtime
We can adapt to integer size at runtime

unsigned short i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;

int width = 3; int offset = 5;

This time we’ll have to compute the mask

/* mask is now 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 */

unsigned short mask = ~0;

/* mask is now 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */

mask = mask >> (number_of_bits- width) << (offset);

Now, finish the job as before

(i & mask) >> offset == 0b 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;

constnumber_of_bits= sizeof(unsigned short) * 8;

putting new value in a bit field
Putting new value in a bit field

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t new_value = 0b 0 1 0; /* value we want *

uint16_t mask = 0b 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1;

“and” together i and mask

(i & mask) == 0b 1 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0;

putting new value in a bit field1

Important: we have zeros where new value is going

Putting new value in a bit field

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t new_value = 0b 0 1 0; /* value we want *

uint16_t mask = 0b 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1;

“and” together i and mask…

(i & mask) == 0b 1 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0;

putting new value in a bit field2
Putting new value in a bit field

uint16_t i = 0b 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0;

uint16_t new_value = 0b 0 1 0; /* value we want *

uint16_t mask = 0b 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1;

“and” together i and mask…

(i & mask) == 0b 1 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0;

… shift the new value and use “or” to combine

(i | (new_value << 5)) == 0b 1 0 0 1 1 1 0 0 0 1 0 0 1 1 1 0;

very common idiom single bit flags
Very common idiom – single bit flags

One bit each

/* Flag definitions */

const uint16_t HI_PRIORITY = 0x8000;

const uint16_t SECURE = 0x4000;

const uint16_t ARCHIVED = 0x2000;

const uint16_t BEAUTIFUL = 0x0002;

constuint16_t SPECTACULAR = 0x0001;

very common idiom single bit flags1

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 = 0b1000000000000000;

const uint16_t SECURE = 0b0100000000000000;

const uint16_t ARCHIVED = 0b0010000000000000;

const uint16_t BEAUTIFUL = 0b0000000000000010;

constuint16_t SPECTACULAR = 0b0000000000000001;

initializing flags

Use | to combine bits

Initializing flags

/* Flag definitions */

const uint16_t HI_PRIORITY = 0b1000000000000000;

const uint16_t SECURE = 0b0100000000000000;

const uint16_t ARCHIVED = 0b0010000000000000;

const uint16_t BEAUTIFUL = 0b0000000000000010;

constuint16_t SPECTACULAR = 0b0000000000000001;

uint16_t myflags = SECURE | BEAUTIFUL; /* secure and beautiful */

testing flags

Test flags with &  remember C treats anything != 0 as true!

Testing flags

/* Flag definitions */

const uint16_t HI_PRIORITY = 0b1000000000000000;

const uint16_t SECURE = 0b0100000000000000;

const uint16_t ARCHIVED = 0b0010000000000000;

const uint16_t BEAUTIFUL = 0b0000000000000010;

constuint16_t SPECTACULAR = 0b0000000000000001;

if (myflags & BEAUTIFUL) {…}; /* if beautiful */

testing flags1
Testing flags

Testing multiple flags on

/* Flag definitions */

const uint16_t HI_PRIORITY = 0b1000000000000000;

const uint16_t SECURE = 0b0100000000000000;

const uint16_t ARCHIVED = 0b0010000000000000;

const uint16_t BEAUTIFUL = 0b0000000000000010;

constuint16_t SPECTACULAR = 0b0000000000000001;

if ((myflags& (BEAUTIFUL | SECURE)) ==

(BEAUTIFUL | SECURE)){…}; /* if beautiful and secure */

turning flags on

Us | to turn on additional flags

Turning flags on

/* Flag definitions */

const uint16_t HI_PRIORITY = 0b1000000000000000;

const uint16_t SECURE = 0b0100000000000000;

const uint16_t ARCHIVED = 0b0010000000000000;

const uint16_t BEAUTIFUL = 0b0000000000000010;

constuint16_t SPECTACULAR = 0b0000000000000001;

myflags |= ARCHIVED; /* now it’s archived too */

turning flags off

To turn off, & with all the other flags!

Turning flags off

/* Flag definitions */

const uint16_t HI_PRIORITY = 0b1000000000000000;

const uint16_t SECURE = 0b0100000000000000;

const uint16_t ARCHIVED = 0b0010000000000000;

const uint16_t BEAUTIFUL = 0b0000000000000010;

constuint16_t SPECTACULAR = 0b0000000000000001;

myflags &= ~BEAUTIFUL; /* but not beautiful anymore  */