· This function works for ASCII but fails for EBCDIC.
· In ASCII, corresponding upper and lower case letters are a fixed distance apart as numeric values
· Letters are also contiguous
Portable character functions and macros
semantics of function or macro
returns 1 <=> c is a digit
returns 1 <=> c is uppercase
converts c to uppercase
converts c to lowercase
· To overcome this common problem, the header is available (and required under ANSI).
· This header defines a family of functions and macros for doing character tests and conversions that are independent of the character set
· Each installation will provide its own to do whatever is necessary
· Now we can rewrite our lower function using these macros:
#include int lower(int c)
if ( isupper(c) )
· The C language does not specify whether variables of type char are signed or unsigned quantities.
· The C definition guarantees that any character in a machine's standard character set will never be negative.
· For portability, if you use characters as integers to store non-character data, specify whether it is signed or unsigned.
· When passing or receiving characters to and from functions, people often use int to store characters.
· Problems sometimes arise when users must be able to store an arbitrary character and EOF (-1) in a character variable. In the EBCDIC character set, it already needs all 256 possible values but adding EOF requires 257.
Type conversions -- A.6, p.198, K&R · The following conversions are performed in an arithmetic expression of mixed types
· Otherwise, if either is double, convert the other to double
· Otherwise, if either is float, convert the other to float
· Otherwise if either is unsigned long int, convert the other to unsigned long int
· Otherwise, if one operand is long int and the other is unsigned int, the effect depends on whether long int can represent all values of an unsigned int; if so, the unsigned int operand is converted to long int; if not, both are converted to unsigned long int
· Otherwise, if one operand is long int, convert the other to long int
· Otherwise, if either operand is unsigned int, convert the other to unsigned int
· Otherwise both operands have type int, i.e. smaller operands are promoted to int.
· Under ANSI, unsigned-ness of operands is not propagated.
Type conversion - the distance program
double speed, distance;
printf("Enter the number of hours: ");
printf("Enter the speed in MPH: ", &speed);
distance = hours * speed;
printf("You travelled %.2f miles "
"at %.2f MPH in %d hours\n",
distance, speed, hours);
The mixed mode expression in question is hours * speed
It is important to understand why the computation of result1 uses floating point division while the computation of result2 uses integer division
Once again, all expressions are evaluated from the simplest, innermost expression outward
Increment and decrement operators · Unary operators ++ and -- increment and decrement their respective operands
· highest precedence (same as unary -)
· right to left associativity
Equivalent C code
y = ++ x;
x = x + 1; /*increment*/
y = x; /*use result*/
y = x ++;
y = x; /*use value*/
x = x + 1; /*increment*/
y = -- x;
x = x - 1;
y = x;
y = x --;
y = x;
x = x - 1;
z = z + 1;
· When ++ or -- are placed beforethe operand, they are called pre-increment and pre-decrement respectively.
· the return value of the expression is the new value of the operand
· When ++ or -- are placed after the operand, they are called post-increment and post-decrement respectively
· the return value of the expression is the original value of the operand
· Cannot apply ++ or -- to something cannot be an lvalue
· An lvalue is anything that can be updated, for instance on the left hand side of an assignment statement
· The expression
· However, the expression
is legal and equivalent to
x[i] = x[i] + 1
ANSI Note (p. 39) "Between the previous and next sequence point, an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored."
· Thus, if a variable is updated more than once within an expression between two consecutive sequence points, the behavior is undefined. example
i = 1;
i = ++i + 1;
· What gets assigned to i?
· Two assignments are being requested, but ANSI specifies that i shall have its stored value modified at most once.
· The resulting value of ++i will propagate through the expression, but the store may or may not occur.
· Consequently, the compiler may choose to allow the ++i to actually store into i or let the assignment statement store into i.
· Thus, only one update to i will win and thus i may be either 2 or 3.
Example expressions · In the table below, assume that the following declarations are in scope.
int a = 1, b = 2, c = 3, d = 4;
· The following table gives an expression, the equivalent fully parenthesized expression, the value of the expression, and then the subsequent values of a, b, c, and d after its evaluation.
· Assume that these expressions are evaluated independent of each other.
a * b / c
(a * b) / c
a * b % c + a
((a * b) % c) + a
++ a * b - c --
((++a) * b) - (c--)
7 - - b * ++ d
7 - ((-b) * (++d))
Illustration of third row
Assignment operators and expressions · In C, any expression can be a statement.
· In Pascal, one uses an assignment statement.
· In C, assignments are simply expressions.
· As a result, it is perfectly legal to write the following meaningless code in C.
3; /* valid */
4+5; /* valid */
Assignments are expressions · The return value of an assignment expression is the value that just got assigned
· The object getting updated by the assignment is called an lvalue
· The object (expression) being assigned to it is called an rvalue example
x = 5 + 7;
· In this example, x is the lvalue, 5+7 is the rvalue, and the return value of the entire expression is 12.
Example of assignments being expressions · The following three statements
b = 2;
c = 3;
a = b + c;
may be written as one statement
a = (b = 2) + (c = 3);
example · Assignment operators associate right to left
· Thus, the following expression
a = b = c = 0;
is equivalent to writing
a = (b = (c = 0));
which in turn is equivalent to writing
c = 0;
b = 0;
a = 0;
· Note that because assignment statements associate right to left, variables a, b, and c are all lvalues.