480 likes | 595 Views
Week 3 - Wednesday. CS222. Last time. What did we talk about last time? Preprocessor directives #define , #include , etc. Other C features sizeof , const ASCII table printf () format strings Introduction to bitwise operations. Questions?. Project 1. Quotes.
E N D
Week 3 - Wednesday CS222
Last time • What did we talk about last time? • Preprocessor directives • #define, #include, etc. • Other C features • sizeof, const • ASCII table • printf() format strings • Introduction to bitwise operations
Quotes Sometimes the slightest shift in the way you look at things, a seemingly insignificant change in perspective can alter your life forever. Anonymous
Bitwise operators • Now that we have a deep understanding of how the data is stored in the computer, there are operators we can use to manipulate those representations • These are: • & Bitwise AND • | Bitwise OR • ~ Bitwise NOT • ^ Bitwise XOR • << Left shift • >> Right shift
Bitwise AND • The bitwise AND operator (&) takes: • Integer representations a and b • It produces an integer representation c • Its bits are the logical AND of the corresponding bits in a and b • Example using 8-bit char values: chara = 46; charb = 77; char c = a & b; //12
Bitwise OR • The bitwise OR operator (|) takes: • Integer representations a and b • It produces an integer representation c • Its bits are the logical OR of the corresponding bits in a and b • Example using 8-bit char values: chara = 46; charb = 77; char c = a | b; //111
Bitwise NOT • The bitwise NOT operator (~) takes: • An integer representation a • It produces an integer representation b • Its bits are the logical NOT of the corresponding bits in a • Example using 8-bit char values: chara = 46; charb = ~a; // -47
Bitwise XOR • The bitwise XOR operator (^) takes: • Integer representations a and b • It produces an integer representation c • Its bits are the logical XOR of the corresponding bits in a and b • Example using 8-bit char values: chara = 46; charb = 77; char c = a ^ b; //99
Swap without a temp! • It is possible to use bitwise XOR to swap two integer values without using a temporary variable • Behold! • Why does it work? • Be careful: If x and y have the same location in memory, it doesn't work • It is faster in some cases, in some implementations, but should not generally be used x = x ^ y; y = x ^ y; x = x ^ y;
Bitwise shifting • The << operator shifts the representation of a number to the left by the specified number of bits • The >> operator shifts the representation of the number to the right by the specified number of bits • Ignoring underflow and overflow, left shifting is like multiplying by powers of two and right shifting is like dividing by powers of two chara = 46; charb = a << 2; //-72 chara = 46; charb = a >> 3; //5
Shift and mask examples • Things smaller than int will be promoted to int • What are the following? • 4 & 113 • 15 | 39 • 31 << 4 • 108 >> 5 • ~80
Why do we care about bitwise operations? • The computer uses bitwise operations for many things • These operations are available for our use and are very fast • Shifting is faster than multiplying or dividing by powers of 2 • You can keep a bitmask to keep track of 32 different conditions • That's quite a lot of functionality for 4 bytes!
Precedence • Operators in every programming language have precedence • Some of them are evaluated before others • Just like order of operations in math • * and / have higher precedence than + and – • = has the very lowest precedence • I don't expect you to memorize them all, but • Know where to look them up • Don't write confusing code
Insane precedence example • What happens here? • x++ >> 5 == 4 % 12 & 3 • It's also worth noting that precedence doesn't tell the whole story • What about multiple assignments in a single line of code? • C doesn't give you guarantees about what happens when • The following could have different results on different compilers: printf("%d %d", x++, (x + 5)); a[x] = x++; x = x++;
Control flow • Sequences of statements surrounded by braces are treated like a single statement with no value • Braces can be thrown in whenever you want • We used to say that "braces were optional" for one-line blocks, but this is the more accurate way to look at it • An expression can always become a statement inta = 150; a; //legal in C, illegal in Java
if statements • Like Java, the body of an if statement will only execute if the condition is true • The condition is evaluated to an int • True means not zero • An else is used to mark code executed if the condition is false Sometimes this is natural and clear; at other times it can be cryptic.
Anatomy of an if Any expression that has a value The if part if( condition ) statement Any single statement ending in a semicolon or a block in braces
Anatomy of an if-else if( condition ) statement1 else statement2 Two different outcomes
Nesting • We can nest if statements inside of other if statements, arbitrarily deep • Just like Java, there is no such thing as an elseif statement • But, we can pretend there is because the entire if statement and the statement beneath it (and optionally a trailing else) is treated like a single statement
switch statements • switch statements allow us to choose between many listed possibilities • Execution will jump to the matching label or to default (if present) if none match • Labels must be constant (either literal values or #define constants) • Execution will continue to fall through the labels until it reaches the end of the switch or hits a break • Don't leave out break statements unless you really mean to!
Anatomy of a switch statement switch( data ) { case constant1: statements1 case constant2: statements2 … case constantn: statementsn default: default statements }
Duff's device • C has relatively relaxed syntax rules • What the hell is that?! int n = (count + 7) / 8; switch(count % 8) { case0: do { *to++ = *from++; case7: *to++ = *from++; case6: *to++ = *from++; case5: *to++ = *from++; case4: *to++ = *from++; case3: *to++ = *from++; case2: *to++ = *from++; case1: *to++ = *from++; } while(--n > 0); }
Three loops • C has three loops, just like Java • while loop • You don't know how many times you want to run • for loop • You know how many times you want to run • do-while loop • You want to run at least once • Like if statements, the condition for them will be evaluated to an int, which is true as long as it is non-zero • All loops execute as long as the condition is true
while loop • A while loop is the keyword while followed by a pair of parentheses • Within the parentheses is a condition • If the condition is true, the body of the loop will be executed • At the end of the loop, the condition is checked again
Anatomy of a while loop while( condition ) statement
for loop • A for loop consists of three parts: • Initialization • Condition • Increment • The initialization is run when the loop is reached • If the condition is true, the body of the loop will be executed • At the end of the loop, the increment will be executed and the condition checked again • If the condition is empty (nothing in it), it is considered true
Anatomy of a for loop Starting Point Way to Progress for ( initialization ; condition ; increment ) statement Ending Point
The comma operator • C has a comma operator • Expressions can be written and separated by commas • Each will be evaluated, and the last one will give the value for the entire expression int a = 10; int b = 5; intc = a, b, ++a, a + b; //16
Adding the comma to for • Sometimes you want to do multiple things on each iteration • Consider this code to reverse an array • You can even use a comma in the condition part, but it doesn't usually make sense intstart; intend; int temp; for( start = 0, end = length - 1; start < end; start++, end-- ) { temp = array[start]; array[start] = array[end]; array[end] = temp; }
do-while loops • As in Java, there are do-while loops which are useful only occasionally • They work just like while loops except that that they are guaranteed to execute at least once • Unlike a while loop, the condition isn’t checked the first time you go into the loop • Sometimes this is useful for getting input from the user • Don't forget the semicolon at the end!
Anatomy of a do-while loop do statement while( condition );
Infinite loops • Loops can go on forever if you aren’t careful int n = 40; inti = 1; while( i <= 40 ) { printf("%d", i); //supposed to print all the numbers //less than 40, but i never increases }
Infinite for loops • Infinite for loops are unusual, but possible: • This situation is more likely: for( ; ; ) printf("Hey!"); inti; for(i = 0; i < 10; i++ ) { • printf("%d", i); • //lots of other code i--; //whoops, maybe changed from while? }
(Almost) infinite loops • Overflow and underflow will make some badly written loops eventually terminate inti; for( i = 1; i <= 40; i-- ) • //whoops, should have been i++ • printf("%d", i);
Fencepost errors • Being off by one is a very common loop error inti; for( i = 1; i < 40; i++ ) //runs 39 times • printf("%d", i);
Skipping loops entirely • If the condition isn’t true to begin with, the loop will just be skipped • inti; for( i = 1; i >= 40; i++ ) //oops, should be <= • printf("%d", i);
Misplaced semicolon • A misplaced semicolon can cause an empty loop body to be executed • Everything looks good, loop even terminates • But, only one number will be printed: 41 • Misplaced semicolon usually makes a while loop infinite inti; for( i = 1; i <= 40; i++ ); //semicolon is wrong { • printf("%d", i); }
Next time… • Fundamental Linux and systems programming concepts • Lab 3
Reminders • Read LPI chapters 2 and 3 • Project 1 due on Friday by midnight!