CSc 352 Basic C Programming Saumya Debray Dept
CSc 352: Basic C Programming Saumya Debray Dept. of Computer Science The University of Arizona, Tucson debray@cs. arizona. edu
What’s new relative to Java? • Some syntactic differences – a lot of the basic syntax is similar • assignment, conditionals, loops, etc. • The biggest differences are conceptual – procedural rather than object-oriented • no notion of classes and inheritance hierarchies – much closer to the machine • debugging sometimes requires thorough understanding of what’s going on at the machine level – explicit dynamic memory management (malloc, free) – pointers 2
The program development process Simple programs (single source file) source code compiler executable code gcc • • C program created with an editor ASCII text human-readable • • machine code created using compiler binary file not human-readable
The program development process More complex programs (many source files) source files compiler object files file 1. c gcc -c file 1. o linker gcc -c filen. c gcc -c file 2. o … file 2. c filen. o executable code
A simple program 5
A simple program a simple C program that prints out “hello” Points to note: • execution begins at main(): every program must have one • printf() is a standard C library routine 6
A simple program… invoking the C compiler warning executable file produced by compiler executing the program 7
Gcc options: -Wall gcc –Wall generates warnings on questionable constructs • if no return type is specified for a function, it defaults to int • need to supply prototype for “printf” 8
Fixing the compiler warnings specifies prototype for printf() specifies return type explicitly 9
Summary • execution starts at main() – every program should have one • the return type for a function defaults to int – should specify explicitly: good style • need to supply prototypes for functions imported from elsewhere (e. g. , standard libraries) – specified using “#include …” 10
Exercise What is wrong with this C program? factorial(n) { int fact = 1; while ( n > 0 ) { fact *= n; } } return fact; 11
Simple declarations and statements two uninitialized global variables, x and y, of type int a variable, z, of type int, that is local to the function main; initialized to 12 print format specifier: %d = “print a decimal value” simple arithmetic expressions and assignment statements 12
Simple conditionals, while loops if statement while statement error message: sent to stderr return value communicates normal/abnormal execution 13
For loops 14
Function calls, recursion function call recursion 15
Formatted Output: printf() • takes a variable no. of arguments: text: Ch. 3 Sec. 3. 1 – printf(“…fmt. Str…”, arg 1, arg 2, …, argn) • “… fmt. Str…” is a string that can contain conversion specifiers • the no. of conversion specifiers should be equal to n • “regular” (non-%) characters in fmt. Str written out unchanged – each conversion specifier is introduced by ‘%’ • this is followed by additional (optional) characters specifying how wide the output is to be, precision, padding, etc. • the conversion specifier indicates how the specified value is to be interpreted: – d = decimal integer, e. g. : printf(“value = %dn”, n); – x = hex integer, e. g. : printf(“hex value of %d is %xn”, x, x); – f = floating point number, e. g. : printf(“area = %fn”, A); 16
Function calls (cont’d) What happens when this printf() is called? • the arguments are evaluated (as in all C function calls) • factorial(6) evaluated • when factorial() returns, the printf is executed: • printf(“ … ”, 720) • This causes the string factorial(6) = 720 to be printed out 17
Formatted Input: scanf() • takes a variable no. of arguments: text: Ch. 3 Sec. 3. 2 – scanf(“…fmt. Str…”, arg 1, arg 2, …, argn) • • “… fmt. Str…” is a string that can contain conversion specifiers the no. of conversion specifiers should be equal to n argi are locations where values that are read in should be placed each conversion specifier is introduced by ‘%’ – similar to conversions for printf • execution behavior: – uses format string to read in as many input values from stdin as it can – return value indicates the no. of values it was able to read • return value of EOF (-1) indicates no further input (“end of file”). 18
scanf() • Specifying where to put an input value: – in general we need to provide a pointer to the location where the value should be placed • for a scalar variable X, this is typically written as &X – Examples: • scanf(“%d”, &n) : read a decimal value into a variable n • scanf(“%d %d %d”, &x, &y, &z) : read three decimal values and put them into variables x, y, z respectively – suppose the input contains the values 12, 3, 71, 95, 101. Then: » x 12; y 3; z 71; return value = 3 – suppose the input contains the values 19, 23. Then: » x 19; y 23; z is unassigned; return value = 2 19
Exercise Which of these are correct? int x; printf(“%dn”, x); int x, y; printf(“%d”, x, y); int x, y, z; printf(“%d %d %d”, x, y, z); int x, y; printf(%d, x, y); int f(int n); printf(“f(%d)= %dn”, n, f(n)); int x, y; printf(“%d %dn”, x); 20
Exercise Which of these are correct? int x; printf(“%dn”, x); int x, y; printf(“%d”, x, y); X int x, y, z; printf(“%d %d %d”, x, y, z); int x, y; printf(%d, x, y); X int f(int n); printf(“f(%d)= %dn”, n, f(n)); int x, y; printf(“%d %dn”, x); X wrong no. of arguments format specifier needs to be a string “. . . “ wrong no. of arguments 21
Exercise Which of these are correct? int x; scanf(“%dn”, x); int x, y; scanf(“%d %d”, &x, &y); int x, y, z; scanf(“%d %d %d”, &x, &y, &z); int x, y; scanf(%d, x, y); int f(int n); scanf(“f(%d)= %dn”, &n, &f(n)); int x, y; scanf(“%d %dn”, &x); 22
Exercise Which of these are correct? int x; scanf(“%dn”, x); X int x, y; scanf(“%d %d”, &x, &y); int x, y, z; scanf(“%d %d %d”, &x, &y, &z); need &x int x, y; scanf(%d, x, y); X format specifier needs to be a string “. . . “ int f(int n); scanf(“f(%d)= %dn”, &n, &f(n)); X &f(n) doesn’t make sense int x, y; scanf(“%d %dn”, &x); X wrong no. of arguments 23
Reading inputs: ^C, ^D, and end-of-file source code typing ctrl-D ends input stream ( EOF) keyboard input int main() { while (scanf(“%d”, &n) != EOF) {. . . } } gcc executable the system indicates EOF when there is no more input to read input from file. /a. out < infile control-C kills the process 24
Primitive data types: Java vs. C • C provides some numeric types not available in Java – unsigned • The C language provides only a “minimum size” guarantee for primitive types – the actual size may vary across processors and compilers • Originally C did not have a boolean type – faked it with ints: 0 false; non-0 true • hence code of the form: if ( (x = getnum()) ) { … } // if value read is nonzero – C 99 provides some support for booleans 25
Primitive numeric types: Java vs. C Java byte short int ? long C C size unsigned char typically (and at least) 8 bits unsigned short int typically (and at least) 16 bits signed short int == unsigned short unsigned int 16 or 32 bits signed int same as unsigned int unsigned long int typically (and at least) 32 bits signed long int == unsigned long int typically (and at least) 64 bits signed long int == unsigned long Comments signedness is implementation dependent the “natural” size for the machine Note: the keywords in gray may be omitted 26
Signed vs. unsigned values • Essential idea: – “signed” : the highest bit of the value is interpreted as the sign bit (0 = +ve; 1 = ve) – “unsigned” : the highest bit not interpreted as sign bit • For an n-bit value: – signed: value ranges from 2 n-1 to +2 n-1 1 – unsigned: value ranges from 0 to 2 n 1 • Right-shift operator ( >> ) may behave differently – unsigned values: 0 s shifted in on the left – (signed) negative values: bit shifted in is implementation dependent 27
Booleans • Originally, C didn’t have a separate boolean type – truth values were ints: 0 = false; non-0 = true – still commonly used in programming • C 99 provides the type _Bool – _Bool is actually an (unsigned) integer type, but can only be assigned values 0 or 1, e. g. : _Bool flag; flag = 5; /* flag is assigned the value 1 */ • C 99 also provides boolean macros in stdbool. h: #include <stdbool. h> bool flag; /* same as _Bool flag */ flag = true; 28
Arithmetic operators: Java vs. C • Most of the common operators in C are as in Java – e. g. : +, +=, -, -=, *, /, %, >>, <<, &&, ||, … • C doesn’t have operators relating to objects: new, instanceof • C doesn’t have >>> (and >>>=) – use >> on unsigned type instead 29
Assignment: l-values increment x twice? what’s going on? 30
Assignment: l-values • The left-hand-side (destination) of an assignment has to be a location – this is referred to as an “l-value” • Consider an expression x ++ ++ the outer “++” operator attempts to increment x++ but x++ is an expression that has no location! error the ++ operator assigns the value x+1 to the location of x the expression ‘x ++’ has the value of x, but no location (as a side-effect, x gets incremented) x has a location and a value 31
What can be an l-value? • l-values: – names of variables of arithmetic type (int, char, float, etc. ) – array elements: x[y] – also: • structs, unions, pointers, etc. (to be discussed later) • operations involving pointers (to be discussed later) • Not l-values: – names of arrays, functions – result of an assignment – value returned by a function call 32
Characters and strings • A character is of type char (signed or unsigned) – C 99 provides support for “wide characters” • strings : – an array of characters – terminated by a 0 character (“NUL” : written ‘ ’) – Not a predefined type in C; string operations are provided through libraries C arrays don’t do bound-checking – careless programming can give rise to memory-corruption errors 33
Example of string manipulation declares an array of chars the input analog to printf: “read a value into str” (%s = “string”) print out a string (%s) 34
More strings… waits for input (from stdin) typed in on keyboard: stdin program output (stdout) end-of-file indicated by typing Ctrl-D 35
More strings… Oops! this means the program tried to access an illegal memory address 36
Functions from special libraries • Some library code is not linked in by default – Examples: sqrt, ceil, sin, cos, tan, log, … [math library] – requires specifying to the compiler/linker that the math library needs to be linked in • you do this by adding “ lm” at the end of the compiler invocation: gcc Wall foo. c lm linker command to add math library • Libraries that need to be linked in explicitly like this are indicated in the man pages 37
Bit Operations • C provides operations to manipulate individual bits of values – done properly and in the right places, this can lead to elegant and efficient code – no. of bits per byte may vary across architectures: the macro CHAR_BIT (defined via #include <limits. h>) gives the no. of bits in a byte. 38
Bit Operations Operation Operator Bitwise complement (unary) ~ Bitwise shift >> << Bitwise AND & Bitwise XOR ^ Bitwise OR | precedence high low 39
Bit Masks • We can select (look at, define) specific bits of a value using bit masks (a fixed bit pattern). E. g. : – for least significant bit in a byte: 0 x 1 – for most significant bit in a byte: (0 x 1 << (CHAR_BIT– 1)) • More generally: let MASK = 0 … 0 i+1 1 i 0 i-1 … 00 then, for a value x: i only bit i of x: (x & MASK) x with bit i set to 1: (x | MASK) x with bit i set to 0: (x & ~MASK) 40
Example Use: Representing Fixed-size Sets • Intuition: – each distinct element that can be in the set is assigned a bit position – suppose x is a variable that holds such a set, and p is an element whose assigned position is k. Then: • • • to add p to x: x = x | (1 << k) to check whether x is in p: evaluate x & (1 << k) set union: bitwise or, | set intersection: bitwise and, & set complement: bitwise negation, ~ • But what if the size of the set is too big for an int? 41
Representing Fixed-size Sets • To handle sets that may be too large to represent using a single word (e. g. , int): – each element still gets assigned a fixed position k (now k may be larger than 32 or 64) – use an array of ints (or longs) to represent the set – use a 2 -level mapping to map the position k to a bit position in this array: 1 • first figure out which array element we need • then figure out which bit position in this array we need 42
Representing Fixed-Size Sets: Example • Suppose we have: – a set that can contain upto 350 elements – an int holds 32 bits – an element p corresponds to position 212 in the set • Then: – use an array of 11 ints to represent the set (11 x 32 = 352) – p is in element 7 of this array (e. g. , A[7]) (element 7 holds positions 192– 223) – within element 7 of the array, p is at bit position 20. 43
- Slides: 43