OSU CSE 2421
The C Language – Logical vs Bitwise Operations;Bit Shifting;Casting;Short-Circuit
Required Reading:
Computer Systems: A Programmer’s Perspective, 3rd Edition, Chapter 2 thru Section 2.1.2
J.E.Jones
OSU CSE 2421
<< left-shift
>> right-shift
& bitwise AND
| bitwise OR
^ bitwise exclusive-OR
~ bitwise NOT (complement, not negation)
Bitwise operators
0 is 0
&& logical AND
1 is 1
|| logical OR
! logical NOT
Logical operators
LOGICAL OPERATORS: 0 is FALSE
Everything else is TRUE Practical Result:
< less than
> greater than
<= less than or equal >= greater than or equal == equals
!= does not equal
relational operators
0 if false; 1 if true
Note 1: Bitwise operators evaluate same bit positions in two different operands. Like T/F tables in CSE 2321
Note 2: Logical operators evaluate an expression on each side of the operator, give that expression a value of 1(true) or 0 (false), then perform the logical operation on the whole
Note 3: C has no keywords such as true or false, #defines are used
Note 4: OR, AND, and NOT: Behave differently between bitwise and logical operators.
BITWISE OPERATORS:
J. E. Jones
OSU CSE 2421
a & c
a=10=1010b c= 0=0000b —————-
a=10=1010b c= 1=0001b —————-
a=10=1010b c= 3=0011b —————-
Bitwise (each column of bits is individually combined)
0000b 010
0000b 010
0010b 210
a && c
a=True c=False ———– False
a=True c=True ———– True
a=True c=True ———– True
Logical (value expression is combined)
int a = 10; int c = 0;
int a = 10; int c = 1;
int a = 10; int c = 3;
Does this remind anyone of Foundations I? It should.
J. E. Jones
OSU CSE 2421
a | c
a=10=1010b c= 0=0000b —————-
a=10=1010b c= 1=0001b —————-
a=10=1010b c= 3=0011b —————-
Bitwise (each column of bits is individually combined)
1010b 1010
1011b 1110
1011b 1110
a || c
a=True c=False ———– True
a=True c=True ———– True
a=True c=True ———– True
Logical (value of expression is combined)
int a = 10; int c = 0;
int a = 10; int c = 1;
int a = 10; int c = 3;
Does this remind anyone of Foundations I? It should.
J. E. Jones
OSU CSE 2421
a ^ c
a=10=1010b c= 0=0000b —————-
a=10=1010b c= 1=0001b —————-
a=10=1010b c= 3=0011b —————-
Bitwise (each column of bits is individually combined)
1010b
1011b
1001b
int a = 10; int c = 0;
int a = 10; int c = 1;
int a = 10; int c = 3;
1010
910 The C Programming Language does not define a logical exclusive OR
1110
J. E. Jones
OSU CSE 2421
~a
a=10=1010b —————-
Bitwise (each column of bits is individually changed)
0101b
!a
610 a=True
Logical (value of expression is combined)
———– False
int a = 10;
J. E. Jones
OSU CSE 2421
When we represent values in binary, we can do what is called “shifting” bits either to the right or to the left.
Left shift example: ◦ Binary value:
0111 0101
01 1101 0100 (fill with 0’s)
◦ Left shift 2 places: Bucket
Bit
The Bit Bucket is a fictitious, but often used item
J. E. Jones
OSU CSE 2421
Shifting to the right has 2 options:
◦ Arithmetic shift – typically used when interpreting as signed values ◦ Logical shift – typically used when interpreting as unsigned values
Shift Right Arithmetic
◦ Fills in from the left with copy of Most Significant Bit ◦ Preserves the sign of the value
◦ Used when interpreting the value as B2T
◦ Binaryvalue:
Shift Right Arithmetic 1 bit: Shift Right Arithmetic 2 bits:
11110101 1111 1010 1111 1101
1
◦ If the MSB had been 0, then new bits would be 0s
01
Bit Bucket
Shift Right Logical
◦ Fills in from the left with 0’s
◦ Used when interpreting the binary value as B2U
1
01
◦ Binaryvalue:
Shift Right Logical 1 bit: Shift Right Logical 2 bits:
11110101 0111 1010 0011 1101
The Bit Bucket is a fictitious, but often used item
J. E. Jones
OSU CSE 2421
Used to compare two values
◦ < <= > >= (Higher precedence than == and !=) ◦== !=
Precedence order is given above, L-R associativity
Arithmetic operators have higher precedence than relational
operators
An expression that is TRUE evaluates to a nonzero number
(generally 1). A FALSE expression evaluates to zero.
◦ For example, the expression (0 == 2) evaluates to 0.
◦ while the expression (2 == 2) evaluates to a 1 (non-zero technically, but usually 1).
J. E. Jones
OSU CSE 2421
ANSI C does not have a distinct Boolean type
◦ int is used instead (usually, but other types are possible)
0 is treated as FALSE
Non-zero is treated as TRUE i = 0;
while (i – 10) { …
i = i + 1; }
◦ As long as (i-10) 0 it is considered TRUE, and the body of the while loop will execute.
(Later versions of C have Boolean type)
J. E. Jones
OSU CSE 2421
ANSI C does not have a distinct Boolean type
◦ int is used instead (usually, but other types are possible)
0 is treated as FALSE
Non-zero is treated as TRUE i = 0;
while (i – 10) { …
}
i = i + 3; /* what happens here? */
◦ As long as (i-10) 0 it is considered TRUE, and the body of the while loop will execute.
(Later versions of C have Boolean type)
J. E. Jones
OSU CSE 2421
Short-Circuit Evaluation: Relational statements stop evaluating once a statement’s value is definitive
◦ In (x && y), if 1st condition evaluates to false (e.g. if expression x==0), evaluation stops
◦ It does not matter what the outcome of the y expression is because (x && y) will always evaluate to false. y is not evaluated or compared (i.e. instructions in y expression are not executed)
◦ Same for OR if first expression evaluates to 1 (TRUE).
◦ XOR would have to check both items (Why??)
This can cause buggy code (or not!)
◦ This is a valid way to write code
◦ There are many arguments made that it can be a correct and expedient way to write some code
◦ Be very cautious
J. E. Jones
OSU CSE 2421
Short-Circuit Evaluation:
func1(float a, float b){
if ((b !=0.0f) && (a/b< 0.5f)){
printf(“ The result of func1 is %f.4\n”, ((a*b) + (a/b))); }
else {
printf(“ The result of func1 is undefined.\n”);
}
return; }
In this example, short-circuit evaluation saves your bacon!
Without short-circuit, this code will seg fault when b=0.0f and a/b is computed.
NOTE: (b !=0.0f) and (a/b< 0.5f) are logical expressions and have values of TRUE or FALSE.
J. E. Jones
OSU CSE 2421
Short-Circuit Evaluation:
func1(int a, int b){
int func_result = 1;
if ((b ==0) && ((func_result = (++a*b+3)))){
printf(“ The result of func1 is %d\n”,a*func_result); }
return;
In this example, short-circuit evaluation might cause you problems because the variable a and func_result sometimes change value in the 2nd expression.
NOTE: (b==0) and ((func_result = (++a*b+))) are logical expressions and have values of TRUE or FALSE.
J. E. Jones
OSU CSE 2421
• Type casting – EXPLICIT
• You purposely convert a variable from one data type to another data type in
your code
• Syntax: (type-name) variable
• Type combination and promotion - IMPLICIT type casting
• (‘a’–32)=97–32=65(ifusedasachar=‘a’)
• Smaller type (char) is “promoted” to be the same size as the larger type (int),
remember that constants default to int.
• Determined at compile time – type of the whole expression is based purely
on the types of the values in the expressions
• Does not lose information – convert from type to compatible larger type
• Whether the casting is implicit or explicit, the compiler will create separate storage for the cast value, and any operands that are necessary to determine it. [See next slide for example]
32
J. E. Jones
OSU CSE 2421
The usual arithmetic conversions are implicitly performed to cast values of distinct types to a common type.
-Compiler first performs integer promotion (promotion of char to int)
-short data type is ignored
-If operands still have different types, then any variables or constants in operand expressions are converted to the type that appears highest in the following hierarchy (except any variables that were already of that type; for those, no conversion is necessary)
J. E. Jones
OSU CSE 2421
The following code is supposed to scale a homework score in the range 0-20 to be in the range 0-100.
cnvt_score(){
int score;
/* score gets set in the range 0<=score <=20 */ score = (score / 20) * 100; /*convert to
return(score); }
Does this work?
percentage*/
3J.4E. Jones
OSU CSE 2421
This does not work! Unfortunately, score will almost always be set to 0 for this code because the integer division in the expression (score/20) will be 0 for every value of score less than 20.
• Thefixistoforcethequotienttobecomputedasafloating-point number even though it will truncate to an int when assigned to score
score = ((double)score / 20) * 100; /*OK – double floating-point division with explicit cast */
score = (score / 20.0) * 100; /*OK – double floating-point division with implicit casting because float (double) constant 20.0 */
score = (int)(score / 20.0) * 100; /*NO -- the (int)cast truncates the floating quotient back to 0 if score < 20 prior to multiplication */
35
J. E. Jones