CS计算机代考程序代写 compiler Microsoft PowerPoint – 4_C_Op_Precedence_Redirection

Microsoft PowerPoint – 4_C_Op_Precedence_Redirection

O
SU

C
SE

2
42

1

J.E.Jones

Required Reading:
Computer Systems: A Programmer’s Perspective, 3rd Edition,
Chapter 1 thru Section 1.3

Pointers on C,
Chapter 5 thru Section 5.1.3, 5.3 through the end of the chapter

O
SU

C
SE

2
42

1

J. E. Jones

 lvalue/Lvalue/L-value: That operand found on the left
side of the assignment operator.
◦ All L-values must be modifiable since they are being assigned

a value.
 rvalue/Rvalue/R-value: That expression found on the

right side of the assignment operator.
◦ R-values can be constants, expressions, be a return value from

a function, etc.

O
SU

C
SE

2
42

1

J. E. Jones

Operator Category Duty Operator Category Duty
= Assignment Equals ‐‐ Mathematical Decrement by 1
+ Mathematical Addition & Bitwise AND
‐ Mathematical Subtraction | Bitwise Inclusive OR
* Mathematical Multiplication ^ Bitwise Exclusive OR
/ Mathematical Division << Bitwise Shift bits left % Mathematical Modulo >> Bitwise Shift bits right
> Comparison Greater than ~ Bitwise One’s Complement
>= Comparison Greater than or equal to + Unary Positive
< Comparison Less than ‐ Unary Negative <= Comparison Less than or equal to * Unary Pointer == Comparison is equal to & Unary Address != Comparison is not equal to sizeof Unary Returns size of an object && Logical AND . Structure Element Access || Logical OR ‐> Structure Pointer element Access
! Logical NOT ?: Conditional odd ‘if’ expression;
++ Mathematical Increment by 1 not often used

O
SU

C
SE

2
42

1

J. E. Jones

 C operators can be classified according to the number of operands
which they take.

 C has unary operators, binary operators, and one ternary operator (the
conditional operator ? : )

 The operands of C operators are expressions, which can be constants,
variables, or expressions which contain one or more operators.

 Expressions will always be evaluated by the code which the compiler
generates; that is, an expression has a value (which has a type, of
course).

 There is a table of operators posted on Piazza which shows which
operators are unary, binary or ternary, and the precedence and
associativity of each operator (precedence/associativity covered
below).

4

O
SU

C
SE

2
42

1

J. E. Jones

 Precedence refers to the relationship between two operators in terms of the
order in which the operations are performed.

 Precedence is a binary relation, that is, it is defined with respect to pairs of
(adjacent) operators. Binary operators are adjacent if they have one operand
in common; unary operators are adjacent if they have the same operand.

 We can always enforce a precedence different from the precedence
specified by the language for 2 operators by using parentheses, because
operations inside parentheses are done first (Have the highest precedence).

 If two adjacent operators have the same precedence, then associativity is
relevant.

 L-R associativity means that the operation specified by the leftmost
operator is done first, and then the one specified by the rightmost operator.
R-L associativity, of course, means the opposite order.

Bottom Line: P&A in C is just like math class, but there are a
few “new” operators

O
SU

C
SE

2
42

1

J. E. Jones

#include
/* program to show associativity of the “/” operator */
int main() {

float num1;
float num2;
float num3;
num1 = 2.0 / 1.0 / 2.0;
num2 = (2.0 / 1.0) / 2.0;
num3 = 2.0 / (1.0 / 2.0);
printf(“num1 is: %f \n”, num1);
printf(“num2 is: %f \n”, num2);
printf(“num3 is: %f \n”, num3);

}
 What is printed?

6

O
SU

C
SE

2
42

1

J. E. Jones

#include
/* program to show associativity of the “/” operator */
int main() {

float num1;
float num2;
float num3;
num1 = 2.0 / 1.0 / 2.0;
num2 = (2.0 / 1.0) / 2.0;
num3 = 2.0 / (1.0 / 2.0);
printf(“num1 is: %f \n”, num1); /* num1 is: 1.000000 */
printf(“num2 is: %f \n”, num2);
printf(“num3 is: %f \n”, num3);

}

7

O
SU

C
SE

2
42

1

J. E. Jones

#include
/* program to show associativity of the “/” operator */
int main() {

float num1;
float num2;
float num3;
num1 = 2.0 / 1.0 / 2.0;
num2 = (2.0 / 1.0) / 2.0;
num3 = 2.0 / (1.0 / 2.0);
printf(“num1 is: %f \n”, num1); /* num1 is: 1.000000 */
printf(“num2 is: %f \n”, num2); /* num2 is: 1.000000

Result with L-R associativity */

printf(“num3 is: %f \n”, num3);
}

8

O
SU

C
SE

2
42

1

J. E. Jones

#include
/* program to show associativity of the “/” operator */
int main() {

float num1;
float num2;
float num3;
num1 = 2.0 / 1.0 / 2.0;
num2 = (2.0 / 1.0) / 2.0;
num3 = 2.0 / (1.0 / 2.0);
printf(“num1 is: %f \n”, num1); /* num1 is: 1.000000 */
printf(“num2 is: %f \n”, num2); /* num2 is: 1.000000

Result with L-R associativity */

printf(“num3 is: %f \n”, num3); /* num3 is: 4.000000
Result with R-L associativity */

}
9

O
SU

C
SE

2
42

1

J. E. Jones

 Let’s see how an expression is evaluated, using the precedence and
associativity in C.

 Suppose, before this statement is executed,
◦ a = 1, b = 3, and c = 5, then

d = ++a * c + b++;

 How does the compiler determine the order of operations?

O
SU

C
SE

2
42

1

J. E. Jones

 How does the compiler determine the order of operations?

 We can take the view that the compiler does the binary operation with the
highest precedence first, then next highest, but expressions with unary
operators are not evaluated until they need to be, in order to evaluate a
larger expression of which they are a part.

 We will also suppose that operands of binary operators are evaluated left to
right (this is true for most compilers, and it is true for ours).

 A good practice is to use parentheses to show the order of evaluation,
starting with the binary operator which has the highest precedence, and
going to the lowest, considering associativity where necessary.

 So, let’s try to parenthesize the binary operators in the expression above,
after parenthesizing all unary operator expressions (unary operators have
higher precedence than all binary operators generally).

O
SU

C
SE

2
42

1

J. E. Jones

Parenthesize unary operators:
d = (++a) * c + (b++);

Precedence of binary operators: * first, then +, then =

Now we can add the rest of the parentheses:

d = ((++a) * c) + (b++);

What is d after execution of this statement (Remember, before this
statement, a = 1, b = 3, and c = 5)?

O
SU

C
SE

2
42

1

J. E. Jones

Value of expression
2 5 3

(d = ((++a) * c) + (b++));

d = (2 * 5) + 3

So, d has the value 13 and after the statement is executed
(a = 2, b = 4, and c = 5)

O
SU

C
SE

2
42

1

J. E. Jones

void main()
{

int a, b, c, d;

a=1;
b=3;
c=5;
d = ++a * c + b++;
printf(“d = %d, when no parens are used.\n”, d);
printf(“a=%d, b=%d, c=%d\n”, a, b, c);

a=1;
b=3;
c=5;
d = (++a) * c + (b++);
printf(“d = %d, when some parens are used.\n”, d);
printf(“a=%d, b=%d, c=%d\n”, a, b, c);

a=1;
b=3;
c=5;
d = (((++a) * c) + (b++));
printf(“d = %d, when all parens are used.\n”, d);
printf(“a=%d, b=%d, c=%d\n”, a, b, c);

}

[jones.5684@cse-fac2 test]$ precedence
d = 13, when no parens are used.
a=2, b=4, c=5
d = 13, when some parens are used.
a=2, b=4, c=5
d = 13, when all parens are used.
a=2, b=4, c=5
[jones.5684@cse-fac2 test]$

O
SU

C
SE

2
42

1

J. E. Jones

 In C, assignments are expressions. This means that an assignment expression, just
as any expression, has a value, which is the value of the rightmost expression.

 Assignment operator has lowest precedence (except for the comma operator)
 Embedded assignments – legal anywhere an expression is legal.
◦ This allows multiple assignment: a = b = 1; /*R-L associativity */
◦ We’ll see how these are used in C a bit later.
◦ Other assignment operators (compound assignment operators) – same

associativity – R-L

+= , –= , *= , /= , %=
 e.g., a += 6; equivalent to a = a + 6;

 NOTE: Using an assignment operator (=) is legal anywhere it is legal to compare
for equality (==), so it is not a syntax error (some compilers may give a warning,
although stdlinux compiler will not!!!).

O
SU

C
SE

2
42

1

J. E. Jones

In Spring 1993, in the Operating System development group at SunSoft, we had a
“priority-one” bug report come in describing a problem in the asynchronous I/O
library. The bug was holding up the sale of $20 million worth of hardware to a
customer who specifically needed the library functionality, so we were extremely
motivated to find it. After some intensive debugging sessions, the problem was
finally traced to a statement that read:

x==2;

It was a typo for what was intended to be an assignment statement. The
programmer’s finger had bounced on the “equals’ key, accidentally pressing it
twice instead of once. The statement as written compared x to 2, generated true
or false, and discarded the result.

C is enough of an expression language that the compiler did not complain about a
statement which evaluated an expression, had no side-effects, and simply threw
away the result. We didn’t know whether to bless our good fortune at locating the
problem, or cry with frustration at such a common typing error causing such an
expensive problem

O
SU

C
SE

2
42

1

J. E. Jones

• Mathematical Symbols
• + – * / %
• addition, subtraction, multiplication, division, modulus

• Works for both integers and float
• + – * /
• / operator performs

integer division if both operands are integer, i.e., truncates answer So that there is only an
integer result;
otherwise, if at least one operand is float, performs floating point division (i.e., implicit casting
is used) result contains whole number and fractional decimal result.

• % operator divides two integer operands and gives integer result of the
remainder

• Associativity – L-R.
• Precedence:

1. Anything inside ()
2. * / %
3. + –

O
SU

C
SE

2
42

1

J. E. Jones

 ++a and a++ have the behavior of a = a + 1
◦ (difference is WHEN increment occurs)

 –a and a– have the behavior of a = a – 1
◦ (difference is WHEN decrement occurs)

[Postfix operators have higher precedence than prefix operators]
 NOTE POSITION OF OPERATOR AND WHAT IT MEANS
◦ ++a  a is incremented BEFORE a is evaluated in the expression
◦ –a  a is decremented BEFORE a is evaluated in the expression
◦ a++  a is incremented AFTER a is evaluated in the expression
◦ a–  a is decremented AFTER a is evaluated in the expression
◦ ++a–  most compilers will accept, but behavior is undefined/inexact

(pick a compiler and roll the dice.)

In both examples below, the final value of a is 2

int main()
{

int a = 1;
printf (“ a is %d”, a++);
return 0;

}
/* 1 will be printed */

int main()
{

int a = 1;
printf (“ a is %d”, ++a);
return 0;

}
/* 2 will be printed */

O
SU

C
SE

2
42

1

J. E. Jones

 What values occur here?
◦ If a=4, c=4, b=3,
◦ z = (a++ > c) || (++b <= a) O SU C SE 2 42 1 J. E. Jones  What values occur here? ◦ If a=4, c=4, b=3, ◦ z = (a++ > c) || (++b <= a) ◦ z = (4 > 4) || (4 <= 5)  (4 > 4) evaluates to 0 (or false), a increments to 5 after evaluation
 b increments to 4 before evaluation, (4 <= 5) evaluates to 1 (or true) O SU C SE 2 42 1 J. E. Jones  What values occur here? ◦ If a=4, c=4, b=3, ◦ z = (a++ > c) || (++b <= a) ◦ z = (4 > 4) || (4 <= 5)  (4 > 4) evaluates to 0 (or false), a increments to 5 after evaluation
 b increments to 4 before evaluation, (4 <= 5) evaluates to 1 (or true) ◦ z = 0 || 1 O SU C SE 2 42 1 J. E. Jones  What values occur here? ◦ If a=4, c=4, b=3, ◦ z = (a++ > c) || (++b <= a) ◦ z = (4 > 4) || (4 <= 5)  (4 > 4) evaluates to 0 (or false), a increments to 5 after evaluation
 b increments to 4 before evaluation, (4 <= 5) evaluates to 1 (or true) ◦ z = 0 || 1 ◦ z = 1, a=5, c=4, b=4 O SU C SE 2 42 1 J. E. Jones  What values occur here? ◦ If a=4, c=4, b=3, ◦ z = (a++ <= c) || (++b <= a) ◦ z = (4<= 4) || (4 <= 5)  (4 > 4) evaluates to 1 (or true), a increments to 5 after evaluation
 2nd expression doesn’t execute because of short circuit

◦ z = 1 || unknown (don’t care)

◦ z = 1, a=5, c=4, b=3

O
SU

C
SE

2
42

1

J.E.Jones

Required Reading:
Pointers on C, Section 15.4.2

O
SU

C
SE

2
42

1

J. E. Jones

 In Unix/linux, there are 3 file descriptors that are explicitly defined to
represent 3 distinct data streams: stdin (0), stdout (1) and stderr(2).

IMPORTANT: By default, in Unix/linux, C programs read input from
“standard input (stdin)” (usually, the keyboard) and write output to “standard
output (stdout)” (usually, the screen). Unix/linux error messages go to
“standard error” (stderr) (also defaults to the screen).

 We can change the destination of each of these data streams from the
Unix/linux command line using what is called redirection.

 You can redirect just the input or just the output or just errors (that is, you
do not have to redirect all of them, but you could).

 For labs, from time to time it will be convenient to redirect input and allow
output to go to standard out (the screen). Obviously, there shouldn’t be any
Unix/linux errors to redirect. 

O
SU

C
SE

2
42

1

J. E. Jones

 We can change the destination of any/all these data streams from the
Unix/linux command line using redirection:
◦ < redirects the input, and ◦ > redirects the output,
◦ 2> redirects Unix/linux system errors

NO CODE CHANGES IN OUR PROGRAM!

 If we run the same program from the command line and do not use
redirection, the program reverts to expecting input from the keyboard
and will print output and errors to the screen.

O
SU

C
SE

2
42

1

J. E. Jones

 It is important to make sure that the input file has an end of file (EOF)
indicator at the end. So, when you are creating/editing your input file, be
sure you hit enter at the end of the last line of the file.

 Example:
◦ prog1 < prog1.input  This example runs program, prog1, and rather than looking for input from the keyboard, gets its input from the file prog1.input ◦ You used this mechanism within gdb when you did lab1 (i.e., run< lab1.input1)  The file prog1.input is expected to be in the same directory in which prog1 is executing. The program will not look for the file anywhere else unless a full pathname is specified for the input file.  If you redirect stdin, the program will expect all input that it requires (until the program terminates) to come from the specified file (i.e., you can’t put part of the input to the program in a file and then when the data in the file runs out, input the rest of it from the command line).  Any output to stdout or any Unix/linux errors messages to stderr would go to the screen. O SU C SE 2 42 1 J. E. Jones  Example 1: % prog1 > output.file

 This will run prog1 and write output to output.file
◦ If output.file does not exist, it will create one.
◦ If output.file does exist, any data currently in the file will be erased and only data from the

most current run of prog1 will be in the file.
◦ If you do not use a full pathname for the output file, it will only look for the file in the current

working directory
 Example 2:

% prog1 >> output.file
 This will run prog1 and write output to output.file
◦ If output.file does not exist, it will create one.
◦ If output.file does exist, output from the current run of the program will be appended to the

end of the file.
◦ If you use this option, be very careful not confuse yourself with respect to what output came

from which execution of your program.
 Both examples would expect input to come from the keyboard and any Unix/linux

errors would be sent to the screen
◦ % echo “—————————–2nd run——————–” >>output.file
◦ %prog1 >> output.file

O
SU

C
SE

2
42

1

J. E. Jones

 In most instances, it’s not a good idea to redirect stderr, but from time to time…
 Example 1:

% prog1 2> error.file
 This will run prog1 and write any Unix/linux error messages to error.file
◦ If error.file does not exist, it will create one.
◦ If error.file does exist, any data currently in the file will be erased and only error messages

from the most current run of prog1 will be in the file.
◦ If you do not use a full pathname for the error file, it will look for the file in the current

directory
 Example 2:

% prog1 2>> error.file
 This will run prog1 and write any Unix/linux errors to error.file
◦ If error.file does not exist, it will create one.
◦ If error.file does exist, output from the current run of the program will be appended to the

end of the file.
◦ If you use this option, be very careful not confuse yourself with respect to what errors came

from which execution of your program. It would be sad to find out that you stayed up all night
looking for an error you see in error.file that you fixed before midnight.

 Both examples would expect input to come from the keyboard and stdout would
be sent to the screen

O
SU

C
SE

2
42

1

J. E. Jones

 What if I want to redirect stdout and stderr to the same
file?
◦ prog1 > stdout.file 2>&1
◦ 2>&1 means redirect stderr to wherever stdout

currently goes

 So, do
◦ prog1 > stdout_stderr.file 2>&1

and
◦ prog1 2>&1 >stdout_stderr.file
Do the same thing??

O
SU

C
SE

2
42

1

J. E. Jones

 What if I want to redirect stdout and stderr to the same file?
◦ prog1 > stdout.file 2>&1

 So, do
◦ Prog1 > stdout_stderr.file 2>&1

and
◦ prog1 2>&1 >stdout_stderr.file
Do the same thing??

 No! Order matters!
◦ prog1 > /home/user/stdout_stderr.file 2>&1

This will send both stdout and stderr to stdout_stderr.file

◦ prog1 2>&1 > stdout_stderr.file
This will send stdout to stdout_stderr.file, and stderr to what was previously

stdout.

 When you perform a shell redirection, the left side of the redirection goes to where
the right side of the redirection currently goes. Meaning in 2>&1, it sends stderr
(2) to wherever stdout (1) currently goes.
But if you, afterwards, redirect stdout somewhere else, stderr doesn’t go with it. It
continues to go wherever stdout was previously going. This is why in the first
example, both stdout and stderr will go to the same place, but in the second they
won’t.