Programing in C
Programing in C
Grzegorz Jaboski Department of Microelectronics and Computer Science tel. (631) 26-48 [email protected] http://neo.dmcs.p.lodz.pl/pdsc
C Timeline
1969 - Ken Thompson creates Unix, B from BCPL 1970 - Thompson & Ritchie evolve B to C 1978 - K&Rs The C Programming Language 1982 - ANSI forms a committee on standardizing C 1988 - K&R updated for ANSI Draft 1989 - ANSI approves C (called C89) 1990 - ISO approves C (called C90) 1995 - New committee formed for C9X 1999 - ISO approval (called C99) 2000 - ANSI approves C99
C Timeline
Structural Programming
C, Pascal, Fortran are procedural programming languages. A program in a procedural language is a list of instructions, augmented with loops and branches. For small programs no other organizational principle (paradigm) is needed. Larger programs are broken down into smaller units. A procedural program is divided into functions, such that ideally each has clearly defined purpose and interface to other functions. The idea of breaking a program into functions can be further extended by grouping functions that perform similar tasks into modules. Dividing a program into functions and modules is the key idea of structured programming.
Function B:
local data
Function C:
local data
global data X
global data Y
global data Z
Large number of potential connections between functions and data (everything is related to everything, no clear boundaries) makes it difficult to conceptualize program structure makes it difficult to modify and maintain the program e.g.: it is difficult to tell which functions access the data
5
0100111001001011010001
28
3.1415
'A'
data aggregates
array
structure
stack
queue
tree
On each level...
We do not want to be concerned with the way to represent objects of this level via objects of lower level We want to be concerned with the semantics of data on this level. What is it ? What we can do with it ?
Integer data
10
999
0.001
Characters
'A'
'@'
Number representation:
d31d30 ... d1d0 is a 32 digit number value = d31 B31 + d30 B30 + ... + d1 B1 + d0 B0
Binary:
0b11010 = 124 + 123 + 022 + 121 + 020 = 16 + 8 + 2 #s often written 0b non standard extension = 26 Here 5 digit binary # turns into a 2 digit decimal # Can we find a base that converts to binary easily?
10
Hexadecimal: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
Normal digits + 6 more from the alphabet In C, written as 0x (e.g., 0xFAB5) 1 hex digit represents 16 decimal values 4 binary digits represent 16 decimal values 1 hex digit replaces 4 binary digits
Conversion: BinaryHex
11
Examples:
1010 1100 0011 (binary) = 0xAC3 10111 (binary) = 0001 0111 (binary) = 0x17 0x3F9 = 11 1111 1001 (binary)
MEMORIZE!
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
0 1 2 3 4 5 6 7 8 9 A B C D E F
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
12
Representation called sign and magnitude MIPS uses 32-bit integers. +1 would be: ten 0000 0000 0000 0000 0000 0000 0000 0001 And 1 in sign and magnitude would be: ten 1000 0000 0000 0000 0000 0000 0000 0001
13
Special steps depending whether signs are the same or not 0x00000000 = +0ten 0x80000000 = -0ten What would two 0s mean for programming?
14
What is the result for unsigned numbers if tried to subtract large number from a small one?
Would try to borrow from string of leading 0s, so result would have a string of leading 1s 3 - 4 000011 - 000100 = 111111 With no obvious better alternative, pick representation that made the hardware simple As with sign and magnitude, leading 0s positive, leading 1s negative 000000...xxx is 0, 111111...xxx is < 0 except 11111 is -1, not -0 (as in sign & mag.)
00001 00010 1 2 . . .
10000
...
0ten 1ten 2ten 2,147,483,645ten 2,147,483,646ten 2,147,483,647ten 2,147,483,648ten 2,147,483,647ten 2,147,483,646ten 3ten 2ten 1ten
One zero; 1st bit called sign bit 1 extra negative: no positive 2,147,483,648ten
17
Can represent positive and negative numbers in terms of the bit value times a power of 2:
Example: 1101two
= 1x-(23) + 1x22 + 0x21 + 1x20 = -23 + 22 + 0 + 20 = -8 + 4 + 0 + 1 = -8 + 5 = -3ten
18
Change every 0 to 1 and 1 to 0 (invert or complement), then add 1 to the result Proof: Sum of number and its (ones) complement must be 111...111two
Example: -3 +3 -3 x : 1111 1111 1111 1111 1111 1111 1111 1101two x: 0000 0000 0000 0000 0000 0000 0000 0010two +1: 0000 0000 0000 0000 0000 0000 0000 0011two (): 1111 1111 1111 1111 1111 1111 1111 1100two +1: 1111 1111 1111 1111 1111 1111 1111 1101two
19
Convert 2s complement number rep. using n bits to more than n bits Simply replicate the most significant bit (sign bit) of smaller to fill new bits
2s comp. positive number has infinite 0s 2s comp. negative number has infinite 1s Binary representation hides leading bits; sign extension restores some of them 16-bit -4ten to 32-bit:
1111 1111 1111 1100two 1111 1111 1111 1111 1111 1111 1111 1100two
20
Binary bit patterns above are simply representatives of numbers. Strictly speaking they are called numerals. Numbers really have an number of digits
with almost all being same (000 or 111) except for a few of the rightmost digits Just dont normally show leading digits
If result of add (or -, *, / ) cannot be represented by these rightmost HW bits, overflow is said to have occurred.
00000
00001
00010 unsigned
11110
11111
22
C Integer Types
treated as values with or without sign signed usually stored in 2's complement format same amount of bits, different range
exact size and range of integer types is not defined in the standard, it is implementation-defined
number of bytes occupied by a variable of a given type can be determined using the sizeof() operator range of values of a given type can be determined using macros in limits.h
23
char Type
not defined, whether it is signed or unsigned must store every character from the character set can be qualified with the keyword signed or unsigned by definition, sizeof(char) == 1 at least 8 bits wide
char c1; /* signed or unsigned */ unsigned char c2; signed char c3; printf("%d\n", sizeof(c1)); /* prints 1 */ printf("%d\n", sizeof(char)); /* also prints 1 */
24
CHAR_BIT
CHAR_MAX
The macro yields the number of bits used to represent an object of type char The macro yields the maximum value for type char. Its value is:
SCHAR_MAX if char represents negative values UCHAR_MAX otherwise
CHAR_MIN
The macro yields the minimum value for type char. Its value is:
SCHAR_MIN if char represents negative values zero otherwise
SCHAR_MAX
SCHAR_MIN
The macro yields the maximum value for type signed char The macro yields the minimum value for type signed char The macro yields the maximum value for type unsigned char
25
UCHAR_MAX
Character sets
ASCII Formula for representing English characters as numbers, with each letter assigned a number from 0 to 127; not all of those are really printable characters. An acronym for American Standard Code for Information Interchange. ASCII control characters are presented in the table at the right EBCDIC Extended Binary Coded Decimal Interchange Code IBM's 8-bit extension of the 4-bit Binary Coded Decimal encoding of digits 0-9 (0000-1001).
Char NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
Dec 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Control-Key ^@ ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M ^N ^O ^P ^Q ^R ^S ^T ^U ^V ^W ^X ^Y ^Z ^[ ^\ ^] ^^ ^_
Control Action NULl character Start Of Heading Start of TeXt End of TeXt End Of Transmission ENQuiry ACKnowledge BELl, rings terminal bell BackSpace (non-destructive) Horizontal Tab (move to next tab position) Line Feed Vertical Tab Form Feed Carriage Return Shift Out Shift In Data Link Escape Device Control 1, normally XON Device Control 2 Device Control 3, normally XOFF Device Control 4 Negative AcKnowledge SYNchronous idle End Transmission Block CANcel line End of Medium SUBstitute ESCape File Separator Group Separator Record Separator Unit Separator
26
27
28
int Type
signed type basic integer type, represents natural integer type for the machine at least 16 bits wide can be qualified with the keyword signed or unsigned
int i1; /* signed */ unsigned int i2; signed int i3; printf("%d\n", sizeof(i1)); /* result is implementation defined */
29
long int i1; /* signed */ unsigned long int i2; signed long int i3; long i4; /* same type as i1 */ unsigned long i5; /* same type as i2 */ signed long i6; /* same type as i3 */ printf("%d\n", sizeof(i1)); /* result is implementation defined */
30
short int i1; /* signed */ unsigned short int i2; signed short int i3; short i4; /* same type as i1 */ unsigned short i5; /* same type as i2 */ signed short i6; /* same type as i3 */ printf("%d\n", sizeof(i1)); /* result is implementation defined */
31
long long int i1; /* signed */ unsigned long long int i2; signed long long int i3; long long i4; /* same type as i1 */ unsigned long long i5; /* same type as i2 */ signed long long i6; /* same type as i3 */ printf("%d\n", sizeof(i1)); /* result is implementation defined */
32
INT_MAX
The macro yields the maximum value for type int The macro yields the minimum value for type int The macro yields the maximum value for type unsigned int The same for type long The same for type short The same for type long long
33
INT_MIN
UINT_MAX
Decimal notation:
int: 1234 long int: 1234L, 1234l unsigned int: 1234U, 1234u unsigned long int: 1234UL, 1234ul, 1234Ul, 1234uL long long int: 1234LL, 1234ll unsigned long long: 1234ULL, 1234ull, 1234uLL, 1234Ull
Octal notation:
the same suffixes as above applicable starts with 0x (zero x) 0x31 == 49 the same suffixes as above applicable
Hexadecimal notation:
34
Direct notation:
Octal notation:
'a', 'b', ..., 'z', '0', ..., '9' '\n'- newline '\r'- carriage return '\a'- visible alert '\b'- backspace '\f'- form feed '\t'- horizontal tabulation '\v'- vertical tabulation '\''- single quote '\"'- double quote '\?'- question mark '\\'- backslash
Special characters:
Hexadecimal notation:
35
Floating Point
1.23233, 0.0003002, 3323443898.3325358903 Real means not imaginary Limit on the largest/smallest number represented Depends on number of bits used Limit on the precision 12345678901234567890 --> 12345678900000000000 Floating point numbers are approximate, while integers are exact representation
36
Scientific Notation
+3.4383000E+03 = 3438.3
37
+1.011101 E+2
Normalized so that the binary point immediately follows the leading digit
Note: First digit is always non-zero --> First digit is always one.
38
8 bits
23 bits
Number = -1S * (1 + M) x 2E-127 Allows representation of numbers in range 2-127 to 2+128 (1038) Since the mantissa always starts with 1, we dont have to represent it explicitly Mantissa is effectively 24 bits
39
Sign
63 62
52 51
32
11 bits
31
20 bits
Bias:1023 Mantissa
0
Exponent
32 bits Number = -1S * (1 + M) x 2E-1023 Allows representation of numbers in range 2-1023 to 2+1024(10 308) Larger mantissa means more precision
40
Implemented in hardware (Intel 80-bit) Must support at least p = 32 At least 11 bits for exponent p >= 64 Exponent range >= 15 bits
Single precision
Double precision
41
float double long double not necessarily, can even use base different than 2 floating point characteristics defined in <float.h>
1234.3 constant of type double 12345.5e7 constant of type double 123.4f constant of type float 123.4F constant of type float 123.4l constant of type long double 123.4L constant of type long double
42
The representation of 1/3 is 0.3333 3 * 1/3 1 The same problem with 1/10 in binary
Results from floating-point calculations are almost never exactly equal to the corresponding mathematical value Results from a particular calculation may vary slightly from one computer system to another, and all may be valid. However, when the computer systems conform to the same standard, the amount of variation is drastically reduced. Results may vary with the optimization level
Values can be stored with greater precision in processor registers, than in memory
43
do not use if (a == b) ... use if( fabs(a - b) < error) ... instead
44
Identifiers
Up to 31 chars (letters, numbers, including _) Must begin with a letter Case sensitive! (Url is different from URL)
45
Naming Styles
Styles:
lower_case CAPITAL_CASE camelCase PascalCase (aka TitleCase) szHungarianNotation Invented by Charles Simonyi, a Hungarian, born in Budapest in 1948
Hungarian Notation:
46
Implicit
Integer promotion before operation: char/short int When calling undeclared function, also floating point promotion: float double If one operand is double, the other is made double else if either is float, the other is made float
int a = 3; float x = 97.6F; double y = 145.987; y = x * y; x = x + a;
47
Explicit (type casting) Sometimes you need to change the default conversion behavior
float x = 97.6; x = (int)x + 1;
Almost any conversion does something but not necessarily what you intended!!
48
Example:
int x = 35000; short s = x; printf("%d %d\n", x, s);
Output is:
35000 -30536
49
Constants
This variable now becomes a constant Constant must be assigned a value at a point where it is declared Trying to modify a constant will trigger a compile time error
Boolean Values in C
C89 doesnt have booleans C99 defines a _Bool type Emulate as int or char, with values 0 (false) and 1 or non-zero (true) Allowed by control flow statements:
if ( success == 0 ) { printf( "something wrong" ); }
51
Boolean Values in C
If success is greater than zero, it will be non-zero, but may not be 1; so the above is NOT the same as:
if ( success ) { printf( "Something is rotten in the state of " "Denmark" ); }
52
Enumeration
enum color {BLACK, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, WHITE, COLOR_MAX};
enum boolean { FALSE, TRUE }; enum boolean eAnswer = TRUE;
53
Enumeration
enum boolean { FALSE, TRUE }; enum genre { TECHNO, TRANCE=4, HOUSE }; enum channel { TVP1=1, HBO=32, RTL=44 };
54
Enumeration - typedef
Typedefs will come in handy later on when we talk about structures and function pointers
55
Arithmetic Operators
Mismatched operands are promoted to "wider" type: char/short int float double Integer division truncates the fractional part: 5/2 2
56
Modulo (%)
13 / 5 == 2 13 % 5 == 3 is x odd? is x evenly divisible by y? map 765 to 0 - 360 range convert 18:45 to 12-hour format simulate a roll of a six-sided dice Must be divisible by 4 AND must not be divisible by 100, except years divisible by 400 are always leap years
57
Assignment is an expression its value is the value of the left-hand side after the assignment
58
Increment/Decrement
Pre-increment/decrement (prefix): ++x, --x Post-increment/decrement (postfix): x++, x- ++x acts like x = x + 1 or x += 1 However, be careful when using in expressions!
++x increments first and then returns x x++ returns x first and then increments
int x = 0; assert(x == 0); assert(++x == 1); assert(x == 1); assert(x++ != 2); assert(x == 2);
59
Bitwise Operators
Only for integral types (char, short, int, long, unsigned/signed) Bitwise operators:
Bitwise AND Bitwise inclusive OR Bitwise exclusive OR (XOR) Left shift Right shift One's complement (unary)
Bitwise Operators
Examples:
Bitwise AND Bitwise OR Bitwise XOR Left shift Right shift One's complement
0110 & 0011 0010 0110 | 0011 0111 0110 ^ 0011 0101 01101110 << 2 10111000 01101110 >> 3 00001101 ~0011 1100
Notice: << and >> multiply/divide by 2n >> operator may not work as expected on signed types can perform logical or arithmetical shift (with sign bit duplication) Don't confuse bitwise & | with logical && ||
61
/* * Format of RGBA colors is * * * */ #define GET_ALPHA(val) #define GET_RED(val) #define GET_GREEN(val) #define GET_BLUE(val) ((val) >> 24) (((val) >> 16) & 0xff) (((val) >> 8) & 0xff) ((val) & 0xff) +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | alpha | red | green | blue |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#define MAKE_ARGB(a,r,g,b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
62
Bit Flags
This allows you to pack up to 32 flags into a single unsigned integer Ex:
#define #define #define #define #define READONLY NOSYSLOCK NOOVERWRITE DISCARD NO_DIRTY_UPDATE 0x00000010 0x00000800 0x00001000 0x00002000 0x00008000
Logical:
y y y y
Equal Not equal logical AND logical OR NOT Less-than Less-than-or-equal-to Greater-than Greater-than-or-equal-to
Relational:
y y y y
64
Miscellaneous Operators
ternary
comma
For complicated expressions with multiple operators, precedence rules determine the order of operation:
Ex: c = getchar() != EOF Because != has higher precedence than =, the above is equivalent to c = (getchar() != EOF) Definitely not what we wanted!
(c = getchar()) != EOF
66
Operators
Function calls, nested assignment statements, and increment and decrement operators cause side effects - some variable is changed as a by-product of the evaluation of an expression. In any expression involving side effects, there can be subtle dependencies on the order in which variables taking part in the expression are updated. C does not specify the order in which the operands of an operator are evaluated, except for &&, ||, ?:, and ',' operators. In a statement like x = f() + g(); f may be evaluated before g or vice versa. Intermediate results can be stored in temporary variables to ensure a particular sequence. The order in which function arguments are evaluated is not specified, so the statement
printf("%d %d\n", ++n, power(2, n));/* WRONG */
can produce different results with different compilers. Another typical situation of this kind is represented by the expression a[i] = i++;
68
69
Expressions yield a value: x + 1, x == y, etc. Statements are expressions ending with ; Curly braces { } are used to group statements into a block Blocks are also used for function bodies and if, else, while,for, etc.
70
if Statements
Simple if statement
if (eDay == eMONDAY) printf("I hate Mondays!\n");
if-else
if (eDay == eMONDAY) printf("I hate Mondays!\n"); else printf("How soon 'till the weekend?\n");
if-else-if-else
if (eDay == eMONDAY) printf("I hate Mondays!\n"); else if (eDay == eWEDNESDAY) printf("The weekend is in sight!\n"); else printf("How soon 'till the weekend?\n");
71
switch Statements
int c = getchar(); switch (c) { case '?': printf("Please answer Y or N\n"); break; case 'y': case 'Y': printf("Answer is yes\n"); break; case 'n': case 'N': printf("Answer is no\n"); break; default: printf("By default, the answer is maybe\n"); break; }
Notice: Cases with multiple statements don't require curly braces default is optional but you usually want to include it Don't forget break!
72
while checks the condition and then executes the body do-while executes the body and then checks the condition
int nDone = 0; do { ... } while (!nDone);
73
for Statement
This is equivalent to
expr1; while (expr2) { statements expr3; }
Print 4 spaces
for(i = 0; i < 4; ++i) putchar(' ');
75
break
Use break to break out of a loop (while, do-while, for) First statement after the loop will be executed Skips the remaining statements in the loop body Proceeds to loop condition (while and do-while) or expr3 (for)
continue
76
goto label; ... label: Causes program execution to jump to the label Used indiscriminately, goto is evil and leads to spaghetti code Two cases where its permissible:
77
Arrays
All elements are the same type Kinds of arrays Character arrays (strings) Other arrays Multi-dimensional
78
\0
szMsg[3] refers to the 4th char (not 3rd) 'p' sizeof(szMsg) = size of the array in bytes = 9 (don't forget the '\0'!) = array size / element size = sizeof(szMsg)/sizeof(char)
79
Number of elements
Character arrays
Here's another way to initialize a string char szMyMsg[] = { 'f', 'o', 'o', '\0' };
80
/* uninitialized array */
Can initialize an array with the ={} notation int aryDays[]= { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; In this case, you can leave out the element count because the compiler can figure it out. If element count is specified and the number of initializers is less, the compiler will fill the remaining elements with 0. This provides a handy way to initialize an array with all zeros: int aryDigitCount[10] = { 0 }; You should always initialize automatic arrays; don't assume they are initialized to 0
81
Array sizes
Given an arbitrary array, how do we determine the number of elements? Can't use sizeof if the array is passed into a function Number of elements of an array is usually obtained from:
a terminating element ('\0' for strings, 0 for argv) a separate count variable (e.g. argc) count encoded in the data somehow (e.g. BSTR) a constant (e.g. MAX_SIZE)
2D Arrays
char arySmiley[4][8] = { " -- -- ", " @ @ ", " + ", " |---/ ", /* trailing comma is legal */ };
This is an array of 4 strings each with 8 chars (don't forget \ 0!) A 2D array is really a 1D array, each of whose elements is an array What is the size in bytes?
83
2D Arrays
How do we paint the eyes and mouth? Why only 7 ints when there are 8 chars?
84
Array Caveats
You must make sure you access only valid array elements!
Accessing/modifying elements that are out-of-bounds in C has undefined consequences! ary[-1] and ary[999] will not generate any compiler errors If you are lucky(!), program crashes with
Segmentation fault (core dumped)
85
Function Definition
type func_name( parameter_list )
{ declarations statements }
header
int fact(int n) { int i, product = 1; for (i = 1; i<=n; ++i) product *= i; return product; } } int main(void)
body declarations
statements
86
Function Header
type func_name( parameter_list )
function name
type returned by the function ( void if no value returned) multiple arguments are separated by commas void if no parameters
Examples:
int fact(int n) void error_message(int errorcode) double initial_value(void) int main(void)
Usage:
a = fact(13); error_message(2); x=initial_value();
87
Write your code as collections of small functions to make your program modular
structured programming code easier to debug easier modification reusable in other programs
88
Function Prototypes
If a function is not defined before it is used, it must be declared by specifying the return type and the types of the parameters
double sqrt(double);
tells the compiler that the function sqrt() takes an argument of type double and returns a double. This means, incidentally, that variables will be cast to the correct type; so sqrt(4) will return the correct value even though 4 is int not double.
These function prototypes are placed at the top of the program, or in a separate header file, file.h, included as #include "file.h" Variable names in the argument list of a function declaration are optional:
void f (char, int); void f (char c, int i); /*equivalent but makes code more readable */
If all functions are defined before they are used, no prototypes are needed. In this case, main() is the last function of the program.
89
Function Calls
expressions in the parameter list are evaluated (in no particular order!) results are transformed to the required type parameters are copied to local variables for the function function body is executed when return is encountered, the function is terminated and the result (specified in the return statement) is passed to the calling function (for example main)
int fact (int n) { int i, product = 1; for (i = 2; i <= n; ++i) product *= i; return product; } }
90
Identifiers (i.e. variables etc.) are accessible only within the block in which they are declared.
{ int a = 2; printf(%d\n, a); { int a = 5; printf(%d\n, a); } printf(%d\n, a); } /* a no longer defined */ /* 2 is printed */ /* inner block a */ /* 5 is printed */ /* outer block a */ /* 2 is printed */
outer a masked
A variable that is declared in an outer block is available in the inner block unless it is redeclared. In this case the outer block declaration is temporarily masked. Avoid masking! Use different identifiers instead to keep your code debuggable!
91
Variables defined within a function (including main) are local to this function and no other function has direct access to them!
the only way to pass variables to a function is as parameters the only way to pass (a single) variable back to the calling function is via the return statement
int func (int n) { printf(%d\n,b); return n; } int main (void) { int a = 2, b = 1, c; c = func(a);
return 0;
Exceptions:
Global Variables
Variables defined outside blocks and functions are global, i.e. available to all blocks and functions that follow Avoid using global variables to pass parameters to functions! Only when all variables in a function are local, it can be used in different programs Global variables are confusing in long code
#include <stdio.h> int a = 1, b = 2; /* global variables */ int main (void) { int b = 5; return 0; }
93
/* local redefinition */
Call by Value
Arguments to functions are evaluated, and the copies of the values not any variables in the argument are passed down to the function Good: protects variables in calling function
n in calling function
94
Storage Classes
Storage class is related to the scope of the variable There are four storage classes:
auto is the default and the most common Memory for automatic variables is allocated when a block or function is entered. They are defined and are local to the block. When the block is exited, the system releases the memory that was allocated to the auto variables, and their values are lost. Declaration:
95
extern
Global variables (defined outside functions) and all functions are of the storage class extern or static and storage is permanently assigned to them To access an external variable, which is defined elsewhere, the following declaration is used:
extern type variable_name; it tells the compiler, that the variable variable_name with the external storage class is defined somewhere in the program
Within a file variables defined outside functions have external storage class Files can be compiled separately, even for one program. extern is used for global variables that are shared across code in several files
96
2, 3
dont survive
compile as:
static
Static variables are local variables that keep their previous value when the block is reentered. A declaration
will set cnt to zero the first time the function is used; thereafter, it will retain its value from previous iterations. This can be useful, e.g., for debugging: you can insert code like this anywhere without interfering with the rest of the program
{ /* debugging starts here */ static int cnt = 0; printf(*** debug: cnt = %d, v = %d\n,++cnt, v); }
The variable cnt is local to the block and wont interfere with another variable of the same name elsewhere in an outer block; it just increases by one every time this block is encountered. static can be also applied to global variables, it means, that they are local to a file and inaccessible from the other files If not initialized explicitly, static and global variables are initialized to 0 98
Recursion
To understand recursion, you must first understand recursion. A function is called recursive if it calls itself, either directly or indirectly. In C, all functions can be used recursively.
Example:
int sum(int n) { if (n <= 1) return n; else return (n + sum(n - 1)); }
If you dont want to generate an infinite loop, you must provide a condition to end the recursion (here n<=1), which is eventually met. Recursion is often inefficient as it requires many function calls.
99
1.4 x 109 function calls needed to find the 43rd Fibonacci number! (which has the value 433494437) If possible, it is better to write iterative functions
int factorial (int n) /* iterative version */ { for ( ; n > 1; --n) product *= n; return product; }
100
Assertions
If you include the directive
#include <assert.h>
you can use the assert macro: this aborts the program if an assertion is not true. You can disable assertions if you #define NDEBUG
#include <assert.h> #include <stdio.h> int f(int a, int b); int g(int c); int main(void) { int a, b, c; ..... scanf(%d%d, &a, &b); ..... c = f(a,b); assert(c > 0);/* an assertion */ ..... }
101