Sharif University of Technology C Programming Languages Lecturer

  • Slides: 171
Download presentation
Sharif University of Technology C++ Programming Languages Lecturer: Omid Jafarinezhad Spring 2014 Lecture 1

Sharif University of Technology C++ Programming Languages Lecturer: Omid Jafarinezhad Spring 2014 Lecture 1 c programming language overview Department of Computer Engineering

Review Of Course Materials • Overview of the C-portions of C++ – e. g.

Review Of Course Materials • Overview of the C-portions of C++ – e. g. , loops, structs, arrays, basic data types, etc. • A quick tour through C++, focusing primarily on classes, templates, inheritance, and dynamic binding • An in-depth look at defining – – – – abstract data types in C++ focusing primarily on classes, templates, and exception handling single and multiple inheritance dynamic binding pointer-to-member functions in C++ dynamic memory management in C++ container classes in C++ • Traps and pitfalls of using C++ and how to workaround them • Thread and Graphic (2 D and 3 D) programming, Refactoring, TDD, Qt, …

References • P. Deitel, H. Deitel, C++: How to Program, 9 th Edition, Prentice

References • P. Deitel, H. Deitel, C++: How to Program, 9 th Edition, Prentice Hall, 2011. • J. Soulie, C++ Language Tutorial, 2009. Available at http: //www. cplus. com/doc/tutorial/ • M. Fowler, K. Beck, J. Brant, W. Opdyke, D. Roberts, Refactoring: Improving the Design of Existing Code, Addison Wesley, 1999.

Grading policy • • • Assignments : 4 pts Projects: 4 pts Quizzes: 2

Grading policy • • • Assignments : 4 pts Projects: 4 pts Quizzes: 2 pts Midterm: 4 pts Final Exam: 6 pts Programming Contest: +1 pt (bonus)

C History • BCPL , 1967, Martin Richards – writing operating-systems software and compiler

C History • BCPL , 1967, Martin Richards – writing operating-systems software and compiler • B, 1969, Ken Thomson – based on BCPL • C, 1972, Dennis Ritchie – based on BCPL and B – at Bell Laboratories – originally implemented on a DEC PDP-11

C++ Programming Language • early 1980 s, Bjarne Stroustrup – at Bell Labroratory –

C++ Programming Language • early 1980 s, Bjarne Stroustrup – at Bell Labroratory – C++ a superset of C – object-oriented programming • Objects are essentially reusable software components that model items in the real world • filename. cpp

Simple C Program • Examples: // Simplest c program // int is return data

Simple C Program • Examples: // Simplest c program // int is return data type int main() // main is entrance function { int main() return 0; } { statement 1; /* statement 1; Objective: print on screen // …. */ return 0; #include <stdio. h> // preprocessor statements have not ; int main() } welcome to c!!! { } printf("welcome to c!!!"); return 0; // indicate that program ended successfully

Example – – – Header file Constant Main function Variables Input and output Process

Example – – – Header file Constant Main function Variables Input and output Process #include <stdio. h> // (preprocessor ) #define PI 3. 14 // PI constant (preprocessor ) // calculating area of circle int main() { /* variable definition */ float Radius; float Area = 0; // get radius of circle form user printf("Enter Radius : n"); scanf("%f", &Radius); // calculating area of circle Area = PI * Radius; printf(“Area = %f", Area ); } system("Pause"); return 0;

Variable declaration • Before using a variable, you must declare it þ Data_Type Identifier;

Variable declaration • Before using a variable, you must declare it þ Data_Type Identifier; • int width; // width of rectangle • float area; // result of calculating area stored in it • char separator; // word separator þ Data_Type Identifier = Initial_Value; • int width = 10; // width of rectangle • float area = 255; // result of calculating area stored in it • char seperator = ‘, ’; // word separator Data_Type Identifier, Identifier , …. ; • int width, length, temporary; • float radius, area = 0;

Data types • Minimal set of basic data types – primitive data types •

Data types • Minimal set of basic data types – primitive data types • • • int float double char Void • The size and range of these data types may vary among processor types and compilers

Data type qualifiers • Modify the behavior of data type to which they are

Data type qualifiers • Modify the behavior of data type to which they are applied: – Size qualifiers: alter the size of the basic data types: • • short: multiply by 0. 5 long: multiply by 2 short can be applied to: int long can be applied to: int and double – Sign qualifiers: can hold both positive and negative numbers, or only positive numbers. : • signed: + and • unsigned: + • they can be applied to : int and char

Data type size and range Data type Qualifier char int float double Example signed

Data type size and range Data type Qualifier char int float double Example signed char c; unsigned char c; signed short int i; unsigned int i; short i; signed unsigned short int i; long i; short long int i; long signed long i; signed long int i; long int i; signed long int i; float f; double d; long double d; Size 8 8 8 16 16 16 or 32 16 16 32 32 64 64 64 80 -128. . 127 0. . 255 -128. . 127 Range signed (16): -32768. . 32767 unsigned (16): 0. . 65535 signed (32): -2147483648. . 2147483647 unsigned (32): 0. . 4294967295 +/- 3. 4 e +/- 38 (~7 digits) +/- 1. 7 e +/- 308 (~15 digits)

Overflow and Underflow /* The # character indicate a pre-processor directive; it's an instruction

Overflow and Underflow /* The # character indicate a pre-processor directive; it's an instruction to the compiler to make it do something The <> character tell C to look in the system area for the file stdio. h. If I had given the name #include "stdio. h" instead it would tell the compiler to look in the current directory /* #include <stdio. h> /* * Function main begins program execution * Semi-colon is statement terminator, so it is as a signal to the compiler for end of line */ int main() { /* The 2 curly brackets { }, are used to specify the limits of the program block */ char letter = 'A'; // char variable to show ASCII code short. Variable = 32769; // short variable for test overflow // printf command display string on the monitor printf("current value of short. Variable is = %dn", short. Variable); printf("current value of letter is = %d", letter); printf("current value of letter is = %c", letter); system("PAUSE"); // pause the execution to show press any key … return 0; // indicate that program ended successfully } current value of short. Variable is = -32767 current value of letter is = 65 current value of letter is = A

Program Error • Compile-time or syntax – is caused when the compiler cannot recognize

Program Error • Compile-time or syntax – is caused when the compiler cannot recognize a statement • Run-time – E. g. division by zero • Logical – E. g. Overflow and Underflow

Integer constant value • Base 10: 1 915 +8 -90 • Base 8: 074

Integer constant value • Base 10: 1 915 +8 -90 • Base 8: 074 0123 084 • Base 16: 0 x 1 0 X 5 0 x 7 fab • • unsigned: 5000 u 4 U long: 123456789 l 56 L unsigned long: 536489 ul long : 5361254865 LL 25 l. L • Example : – 0 x. ABu 0123 u. L 017 LL

floating-point constant value • A floating-point value contains a decimal point – 33. 5

floating-point constant value • A floating-point value contains a decimal point – 33. 5 0. 0 -657. 983. 2 6. • For example, the value 150. 4582 is represented in scientific notation as – 1. 504582 X 102 • and is represented in exponential notation (by the computer) as – 1. 504582 E+02 – This notation indicates that 1. 504582 is multiplied by 10 raised to the second power (E+02) • The E stands for “exponent”

Char and string constant value • Char c; c = 'A'; // d =

Char and string constant value • Char c; c = 'A'; // d = 65; • String printf("string is array of char!!!"); printf("example of escape sequence is n");

Constant • Constants provide a way to define a variable which cannot be modified

Constant • Constants provide a way to define a variable which cannot be modified by any other part in the code – #define: without memory consume – const: memory consume • #define Identifier constant_value – #define PI 3. 14 – #define ERROR "Disk error " – #define ERROR "multiline message" – #define ONE 1 #define TWO ONE + ONE

Constant • const [Data_Type] Identifier = constant_value; – const p = 3; // const

Constant • const [Data_Type] Identifier = constant_value; – const p = 3; // const int p = 3; – const p; p = 3. 14; // compile error – const p = 3. 14; // p = 3 because default is int – const float p = 3. 14;

Operators • Arithmetic Operators – unary operators • operators that require only one operand

Operators • Arithmetic Operators – unary operators • operators that require only one operand – binary operators • operators that require two operands • • Assignment Operators Equality and Relational Operators Logical Operators Bitwise Operators Conditional Operator Comma Operator sizeof Operator Width * High Operand

Arithmetic Operators • Unary Operator C operation Operator Expression Explanation Positive + a =

Arithmetic Operators • Unary Operator C operation Operator Expression Explanation Positive + a = +3; Negative - b = -4; Increment ++ i++; Equivalent to i = i + 1 Decrement -- i - -; Equivalent to i = i - 1

Arithmetic Operators • Binary Operators C operation Operator Expression Addition + b = a

Arithmetic Operators • Binary Operators C operation Operator Expression Addition + b = a + 3; Subtraction - b = a – 4; Multiplication * b = a * 3; Division / b = a / c; Modulus (integer) % b = a % c;

Division • The division of variables of type integer will always produce a variable

Division • The division of variables of type integer will always produce a variable of type integer as the result • Example Since b is declared as an integer, the result of a/2 is 3, not 3. 5 int a = 7, b; float z; b = 3, b = a / 2; z = a / 2. 0; printf("b = %d, z = %fn", b, z); z = 3. 500000

Modulus • You could only use modulus (%) operation on integer variables (int, long,

Modulus • You could only use modulus (%) operation on integer variables (int, long, char) z = a % 2. 0; // error z = a % 0; // error • Example int a = 7, b, c; b = a % 2; c = a / 2; printf("b = %dn", b); printf("c = %dn", c); Modulus will result in the remainder of a/2. - 7 2 6 3 a/2 integral 1 a%2 remainder

Assignment Operators • lvalue = rvalue; int i; float f; i = 2; //

Assignment Operators • lvalue = rvalue; int i; float f; i = 2; // *&i = 2; 2 = i; // error: invalid lvalue in assignment f = 5. 6; i = f; // i = 5; i = -5. 9; // i = -5;

Assignment Operators • Assignment operators are used to combine the '=' operator with one

Assignment Operators • Assignment operators are used to combine the '=' operator with one of the binary arithmetic or bitwise operators Operator • Example : – c = 9; Expression Equivalent Statement Results += c += 7; c = c + 7; c = 16 -= c -= 8; c = c – 8; c=1 *= c *= 10; c = c * 10; c = 90 /= c /= 5; c = c / 5; c=1 %= c %= 5; c = c % 5; c=4 &= c &= 2 ; c = c & 2; c=0 ^= c ^= 2; c = c ^ 2; c = 11 |= c |= 2; c = c | 2; c = 11 <<= c <<= 2; c = c << 2; c = 36 >>= c >>= 2; c = c >> 2; c=2

Equality and Relational Operators • Equality Operators: Operator Example Meaning == x == y

Equality and Relational Operators • Equality Operators: Operator Example Meaning == x == y x is equal to y != x != y x is not equal to y • Relational Operators: Operator > < >= <= Example x>y x<y x >= y x <= y Meaning x is greater than y x is less than y x is greater than or equal to y x is less than or equal to y

Logical Operators • Logical operators are useful when we want to test multiple conditions

Logical Operators • Logical operators are useful when we want to test multiple conditions – AND – OR – NOT • C has not bool data type, but: – 0: evaluate to false • If(0) printf(" …"); – other: evaluate to true • If(1) printf(" …"); • If(-13) printf(" …");

&& - Logical AND • All the conditions must be true for the whole

&& - Logical AND • All the conditions must be true for the whole expression to be true – Example: if (a == 1 && b == 2 && c == 3) • means that the if statement is only true when a == 1 and b == 2 and c == 3 If (a = 5) … e 1 e 2 Result = e 1 && e 2 0 0 0 false 0 1 0 false true false 1 0 0 true false 1 1 1 true

|| - Logical OR • The truth of one condition is enough to make

|| - Logical OR • The truth of one condition is enough to make the whole expression true • Example: if (a == 1 || b == 2|| c == 3) – means the if statement is true when either one of a, b or c has the right value e 1 e 2 Result = e 1 || e 2 0 0 0 false 0 1 1 false true 1 0 1 true false true 1 1 1 true

! - Logical NOT • Reverse the meaning of a condition • Example: if

! - Logical NOT • Reverse the meaning of a condition • Example: if (!(radius > 90)) – Means if radius not bigger than 90. e 1 Result = !e 1 0 1 false true 1 0 true false

Bitwise Operators • Apply to all kinds of int and char types: – signed

Bitwise Operators • Apply to all kinds of int and char types: – signed and unsigned – char, short, int, long Operator Name & AND Result is 1 if both operand bits are 1 | OR Result is 1 if either operand bit is 1 ^ XOR Result is 1 if operand bits are different ~ Description Not (Ones Complement) Each bit is reversed << Left Shift Multiply by 2 >> Right Shift Divide by 2

Bitwise Operators • Applicable for low level programming, e. g. : – Port manipulation

Bitwise Operators • Applicable for low level programming, e. g. : – Port manipulation – I/O programming • Usually: – &: set OFF one bit – |: set ON one bit – ^: reverse one bit

Conditional Operator • The conditional operator (? : ) is used to simplify an

Conditional Operator • The conditional operator (? : ) is used to simplify an if/else statement – Condition ? Expression 1 : Expression 2; • The statement above is equivalent to: if (Condition) Expression 1; else Expression 2; • Which are more readable?

Comma Operator • (Expression 1 , Expression 2, …); • Example: – int x,

Comma Operator • (Expression 1 , Expression 2, …); • Example: – int x, y, z; – z = (x = 2, y = x + 1); – printf("z = %d", z); int x, y, z; x = 2; y = x + 1; z = y; printf("z = %d", z);

sizeof • The sizeof keyword returns the number of bytes of the given expression

sizeof • The sizeof keyword returns the number of bytes of the given expression or type – returns an unsigned integer result • sizeof variable_Identifier; • sizeof (variable_Identifier); • sizeof (Data_Taype); • Example: – – int x; printf("size of x = %d", sizeof x); printf("size of long = %d", sizeof(long)); printf("size of x = %d", sizeof (x));

Type Casting • Explicit Type cast: carried out by programmer using casting int k,

Type Casting • Explicit Type cast: carried out by programmer using casting int k, i = 7; float f = 10. 14; char c = 'B'; k = (i + f) % 3; // error k = (int)(i + f) % 3; • Implicit Type cast: carried out by compiler automatically f = 65. 6; i = f; //f = (int)f; c = i; // c = (int)i;

Precedence Rules Primary Expression Operators () []. -> Unary Operators * & + left-to-right

Precedence Rules Primary Expression Operators () []. -> Unary Operators * & + left-to-right - ! ~ ++expr --expr (typecast) sizeof right-to-left * / % + >> << < > <= >= Binary Operators == != left-to-right & ^ | && || Ternary Operator ? : right-to-left Assignment Operators = += -= *= /= %= >>= <<= &= ^= |= right-to-left Post increment expr++ - Comma , expr-- left-to-right

Control Structures • Sequence • Decision selection statement – The if statement is called

Control Structures • Sequence • Decision selection statement – The if statement is called a single-selection statement because it selects or ignores a single action. – The if…else statement is called a double-selection statement because it selects between two different actions. – The switch statement is called a multiple-selection statement because it selects among many different actions • Repetition – while – do…while – for

Compound Statements • A statement is a specification of an action to be taken

Compound Statements • A statement is a specification of an action to be taken by the computer as the program executes • Compound Statements is a list of statements enclosed in braces, { }

Decision Structure • One of two possible actions is taken, depending on a condition

Decision Structure • One of two possible actions is taken, depending on a condition • Selection structures are used to choose among alternative courses of action NO YES x < y? Process A Process B

Decision Structure • The flowchart segment below shows how a decision structure is expressed

Decision Structure • The flowchart segment below shows how a decision structure is expressed in C as an if/else statement Flowchart NO C programming language YES x < y? if (x < y) a = x * 2; Calculate a as x plus y. Calculate a as x times 2. else a = x + y;

Decision Structure • The flowchart segment below shows a decision structure with only one

Decision Structure • The flowchart segment below shows a decision structure with only one action to perform C programming language Flowchart NO YES if (x < y) x < y? a = x * 2; Calculate a as x times 2.

Combining Structures NO YES x > min? if (x > min) Display “x is

Combining Structures NO YES x > min? if (x > min) Display “x is outside { the limits. ” if (x < max) printf("x is within the limits"); else printf("x is outside the limits"); } else printf("x is outside the limits"); NO YES x < max? Display “x is outside the limits. ” Display “x is within limits. ”

Example if(x) if(y) printf("Yes"); else printf("No"); if (x < 0) sign = -1; else

Example if(x) if(y) printf("Yes"); else printf("No"); if (x < 0) sign = -1; else if (x == 0) sign = 0; else sign = 1; if(x) { if(y) printf("Yes"); else printf("No"); } if (x < 0. 25) count 1++; else if (x >= 0. 25 && x < 0. 5) count 2++; else if (x >= 0. 5 && x < 0. 75) count 3++; else count 4++; if(x) { if(y) printf("Yes"); } else printf("No");

Case Structure • One of several possible actions is taken, depending on the contents

Case Structure • One of several possible actions is taken, depending on the contents of a variable

Case Structure • indicates actions to perform depending on the value in years_employed If

Case Structure • indicates actions to perform depending on the value in years_employed If years_employed = 2, bonus is set to 200 If years_employed = 1, bonus is set to 100 1 bonus = 100 If years_employed = 3, bonus is set to 400 If years_employed is any other value, bonus is set to 800 CASE years_employed 2 3 bonus = 200 bonus = 400 Other bonus = 800

switch • A switch statement allows a single variable (integer or char) to be

switch • A switch statement allows a single variable (integer or char) to be compared with several possible constants – A constant can not appear more than once, and there can only be one default expression

switch (variable) { case const: statements. . . ; default: statements. . . ;

switch (variable) { case const: statements. . . ; default: statements. . . ; } switch (c = toupper(getch())) { case ‘R’: printf("Red"); break; case ‘G’: printf("Green"); break; default: printf("other"); }

Example switch(betty) { case 1: printf("betty = 1n"); case 2: printf("betty=2n"); break; case 3:

Example switch(betty) { case 1: printf("betty = 1n"); case 2: printf("betty=2n"); break; case 3: printf("betty=3n"); break; default: printf("Not suren"); } CASE betty? 1 betty = 1 2 betty = 2 3 betty = 3 Other Not sure

Repetition Structure • A loop tests a condition, and if the condition exists, it

Repetition Structure • A loop tests a condition, and if the condition exists, it performs an action. Then it tests the condition again. If the condition still exists, the action is repeated. This continues until the condition no longer exists x < y? YES Process A

Repetition Structure • The flowchart segment below shows a repetition structure expressed in C

Repetition Structure • The flowchart segment below shows a repetition structure expressed in C as a while loop Flowchart C programming language while (x < y) x < y? YES x++; Add 1 to x

While while (loop_repetition_condition) statement; OR //Compound statement while (loop_repetition_condition) { statement 1; statement 2;

While while (loop_repetition_condition) statement; OR //Compound statement while (loop_repetition_condition) { statement 1; statement 2; // … }

Controlling a Repetition Structure • The action performed by a repetition structure must eventually

Controlling a Repetition Structure • The action performed by a repetition structure must eventually cause the loop to terminate. Otherwise, an infinite loop is created • In this flowchart segment, x is never changed. Once the loop starts, it will never end • How can this flowchart be modified so it is no longer an infinite loop? x < y? YES Display x

Controlling a Repetition Structure • Adding an action within the repetition that changes the

Controlling a Repetition Structure • Adding an action within the repetition that changes the value of x x < y? YES Display x Add 1 to x

A Pre-Test Repetition Structure • This type of structure is known as a pre-test

A Pre-Test Repetition Structure • This type of structure is known as a pre-test repetition structure. The condition is tested BEFORE any actions are performed – if the condition does not exist, the loop will never begin x < y? YES Display x Add 1 to x

Example while (1); int counter = 0; while (counter < 1000) ; int counter

Example while (1); int counter = 0; while (counter < 1000) ; int counter = 0; while (counter < 9) printf("%dn", counter ++); int counter = 9; while (counter > 0) printf("%dn", counter --); int counter = 0; while (counter < 9) { printf("%dn", counter); counter++; } int counter = 0; while (counter < 9) { printf("%dn", counter ++); }

A Post-Test Repetition Structure • The condition is tested AFTER the actions are performed

A Post-Test Repetition Structure • The condition is tested AFTER the actions are performed – A post-test repetition structure always performs its actions at least once C programming language do { printf(…); x++; } while (x < y); Display x Add 1 to x x < y? YES

do-while do statement; while (loop_repetition_condition) OR do //Compound statement { statement 1; statement 2;

do-while do statement; while (loop_repetition_condition) OR do //Compound statement { statement 1; statement 2; // … } while (loop_repetition_condition)

For for (initial_value ; condition; update_counter) statement; OR // Compound statement for (initial_value ;

For for (initial_value ; condition; update_counter) statement; OR // Compound statement for (initial_value ; condition; update_counter) { statement; // … }

Array • Generic declaration: typename variablename[size]; – – – typename is any type variablename

Array • Generic declaration: typename variablename[size]; – – – typename is any type variablename is any legal variable name size is a number the compiler can figure out For example : int a[10]; Defines an array of ints with subscripts ranging from 0 to 9 There are 10*sizeof(int) bytes of memory reserved for this array. 0 a 1 2 3 4 5 6 7 8 10 – You can use a[0]=10; x=a[2]; a[3]=a[2]; etc. – You can use scanf("%d", &a[3]); 9

Array Representation int A[3]; 0 x 1008 A[2] 0 x 1004 A[1] 0 x

Array Representation int A[3]; 0 x 1008 A[2] 0 x 1004 A[1] 0 x 1000 A[0] All elements of same type – homogenous Last element (index size - 1) First element (index 0) A[-1] array[0] = 3; array[2] = 4; array[10] = 5; array[-1] = 6; No bounds checking! 3 * 4 = 12 sizeof(A)? sizeof(A[0]) = sizeof(A[1]) = sizeof(A[2])? 4

Using Constants to Define Arrays • It is useful to define arrays using constants:

Using Constants to Define Arrays • It is useful to define arrays using constants: #define MONTHS 12 float a [MONTHS]; • However, in ANSI C, you cannot int n; scanf(“%d”, &n); float a[n]; • In GNU C, the variable length array is allowed.

Initializing Arrays • Initialization of arrays can be done by a comma separated list

Initializing Arrays • Initialization of arrays can be done by a comma separated list following its definition • For example: int array [4] = { 100, 200, 300, 400 }; – This is equivalent to: int array [4]; array[0] = 100; array[1] = 200; array[2] = 300; array[3] = 400; • You can also let the compiler figure out the array size for you: int array[] = { 100, 200, 300, 400};

Initializing Arrays • For example: int array [4] = { 100, 200 }; •

Initializing Arrays • For example: int array [4] = { 100, 200 }; • Also can be done by int array [4] = { 100, 200, 0, 0 }; – This is equivalent to int array [4]; array[0] = 100; array[1] = 200; array[2] = 0; array[3] = 0;

Multidimensional Arrays • Arrays in C can have virtually as many dimensions as you

Multidimensional Arrays • Arrays in C can have virtually as many dimensions as you want • Definition is accomplished by adding additional subscripts when it is defined • For example: – int a [4] [3] ; • 2 -dimensional array • 4 * 3 * sizeof(int) – int a[4][3][2] • 3 -dimention array • 4 * 3 * 2 * sizeof(int)

Multidimensional Arrays Representation a[0][0] a[0][1] a[0][2] a[0][3] Row 0 Row 1 Row 2 Column

Multidimensional Arrays Representation a[0][0] a[0][1] a[0][2] a[0][3] Row 0 Row 1 Row 2 Column 0 Column 1 Column 2 Column 3 a[ 0 ][ 1 ] a[ 0 ][ 2 ] a[ 0 ][ 3 ] a[ 1 ][ 0 ] a[ 1 ][ 2 ] a[ 1 ][ 3 ] a[ 2 ][ 0 ] a[ 2 ][ 1 ] a[ 2 ][ 3 ] a[1][0] a[1][1] a[1][2] Column subscript Array name Row subscript a[1][3] a[2][0] a[2][1] a[2][2] a[2][3] int a[n][m] ; &a[i][j] = [(m * i) + j] * (sizeof(int)) + &a[0]

Initializing Multidimensional Arrays • The following initializes a[4][3]: int a[4] [3] = { {1,

Initializing Multidimensional Arrays • The following initializes a[4][3]: int a[4] [3] = { {1, 2, 3} , {4, 5, 6} , {7, 8, 9} , {10, 11, 12} }; • Also can be done by: int a[4] [3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; – is equivalent to a[0][0] = 1; a[0][1] = 2; a[0][2] = 3; a[1][0] = 4; . . . a[3][2] = 12;

Examples • Initialization – Example: • short b[ 2 ] = { { 1,

Examples • Initialization – Example: • short b[ 2 ] = { { 1, 2 }, { 3, 4 } }; 1 2 3 4 – If not enough, unspecified elements set to zero • short b[ 2 ] = { { 1 }, { 3, 4 } }; 1 0 3 4

Examples int a[10]; // Ok int a[2. 5]; // Syntax error int a[-5]; //

Examples int a[10]; // Ok int a[2. 5]; // Syntax error int a[-5]; // Syntax error int a[0]; // Logical error a[3. 6] = 10; // Syntax error or a[3] = 10; a[3. 2] = 10; // Syntax error or a[3] = 10; int b[2][3] = { {1, 2}, {3, 4}, {5, 6} }; // Syntax error

Strings are Character Arrays • Strings in C are simply arrays of characters –

Strings are Character Arrays • Strings in C are simply arrays of characters – Example: char s [10]; • This is a ten (10) element array that can hold a character string consisting of 9 characters • This is because C does not know where the end of an array is at run time – By convention, C uses a NULL character '' to terminate all strings in its library functions • For example: char str [10] = {'u', 'n', 'I', 'x', ''}; • It’s the string terminator (not the size of the array) that determines the length of the string

Accessing Individual Characters • The first element of any array in C is at

Accessing Individual Characters • The first element of any array in C is at index 0. The second is at index 1, and so on. . . char s[10]; s[0] = 'h'; s[1] = 'i’; s[2] = '!'; s[3] = ''; h s i ! ? ? ? [0] [1] [2] [3] [4] [5] [6] [7] [8] ? [9] • This notation can be used in all kinds of statements and expressions in C: – For example: c = s[1]; if (s[0] == '-') … switch (s[1]). . .

String Literals • String literals are given as a string quoted by double quotes

String Literals • String literals are given as a string quoted by double quotes – printf("Long long ago. "); • Initializing char array. . . – char s[10] = "unix"; /* s[4] is ''; */ – char s[ ] = "unix"; /* s has five elements */

Pointer Fundamentals • When a variable is defined the compiler (linker/loader actually) allocates a

Pointer Fundamentals • When a variable is defined the compiler (linker/loader actually) allocates a real memory address for the variable – int x; – &x = 22 f 54; // &x = 22 f 54; // Error x & * 22 F 54 0000 522 F 5 0000 22 F 56 0000 22 F 57 00000011 • When a value is assigned to a variable, the value is actually placed to the memory that was allocated – x = 3; // * (&x) = 3; – *x = 3; // Error

Pointer Fundamentals • When the value of a variable is used, the contents in

Pointer Fundamentals • When the value of a variable is used, the contents in the memory are used – y = x; & * – y = *(&x); x 22 F 54 0000 522 F 5 0000 22 F 56 0000 22 F 57 00000011 • &x can get the address of x (referencing operator &) • The address can be passed to a function: – scanf("%d", &x); • The address can also be stored in a variable …

Pointers • To declare a pointer variable type * Pointer. Name; x • For

Pointers • To declare a pointer variable type * Pointer. Name; x • For example: int x; int * p; //p is a int pointer // char *p 2; p 1 = &x; /* Initializing p 1 */ p & * 22 F 50 ? 22 F 51 ? 22 F 52 ? 22 F 53 ? 22 F 54 00 522 F 5 02 22 F 56 2 F 22 F 57 50 …

Initializing Pointers • Like other variables, always initialize pointers before using them!!! * 22

Initializing Pointers • Like other variables, always initialize pointers before using them!!! * 22 F 50 ? 22 F 51 ? 22 F 52 ? 22 F 53 Compiler p 22 F 54 ? 00 522 F 5 02 22 F 56 2 F 22 F 57 50 x … Developer void main() { int x; int *p; scanf("%d", p); /* Don’t */ p = &x; scanf("%d", p); /* Correct */ } &

Using Pointers • You can use pointers to access the values of other variables,

Using Pointers • You can use pointers to access the values of other variables, i. e. the contents of the memory for other variables • To do this, use the * operator (dereferencing operator) – Depending on different context, * has different meanings • For example: & * & * n n m 3 m 10 p p p int n, m = 3, *p; m 3 p = &m; // Initializing n = *p; *p printf("%dn", n); // 3 p printf("%dn", *p); *p // 3 *P = 10; printf("%dn", n); // 3 printf("%dn", *p); *p // 10 3 3

Pointer Assignment int a = 2, b = 3; int *p 1, *p 2;

Pointer Assignment int a = 2, b = 3; int *p 1, *p 2; p 1 = &a; p 2 = &b; printf("%p %p", p 1 , p 2); *p 1 = *p 2; printf("%d %d", *p 1, *p 2); p 2 = p 1; printf("%p %p", p 1, p 2); printf("%p %p", &p 1, &p 2); & * b 3 a 2 p 1 p 2 & * b 3 a 3 p 1 p 2

Constant Pointers • A pointer to const data does not allow modification of the

Constant Pointers • A pointer to const data does not allow modification of the data through the pointer const int a = 10, b = 20; a = 5; // Error const int *p; int *q; p = &a; *p = 100; // Error : p is (const int *) p = &b; q = &a; *q = 100; // OK !!!

Constant Pointers int x; /* define x */ int y; /* define y */

Constant Pointers int x; /* define x */ int y; /* define y */ /*ptr is a constant pointer to an integer that can be modified through ptr, but ptr always points to the same memory location */ int * const ptr = &x; *ptr = 7; /* allowed: *ptr is not const */ ptr = &y; /* error: cannot assign new address */

Constant Pointers int x = 5; /* initialize x */ int y; /* define

Constant Pointers int x = 5; /* initialize x */ int y; /* define y */ /*ptr is a constant pointer to a constant integer. ptr always points to the same location; the integer at that location cannot be modified */ const int * const ptr = &x; *ptr = 7; /* error: cannot assign new value */ ptr = &y; /* error: cannot assign new address */

Multiple indirection int a = 3; int *b = &a; int **c = &b;

Multiple indirection int a = 3; int *b = &a; int **c = &b; int ***d = &c; int ****f = &d; & * a 3 b c d f

NULL Pointer • Special constant pointer NULL – Points to no data – Dereferencing

NULL Pointer • Special constant pointer NULL – Points to no data – Dereferencing illegal – To define, include <stdlib. h> or <stdio. h> – int *q = NULL;

Generic Pointers: void * • void *: a pointer to anything void *p; int

Generic Pointers: void * • void *: a pointer to anything void *p; int i; char c; p = &i; p = &c; putchar(*(char *)p); type cast: tells the compiler to change an object’s type (for type checking purposes – does not modify the object in any way) • Lose all information about what type of thing is pointed to – Reduces effectiveness of compiler’s type-checking – Can’t use pointer arithmetic

Arithmetic Operations • A pointer may be incremented or decremented – An integer may

Arithmetic Operations • A pointer may be incremented or decremented – An integer may be added to or subtracted from a pointer. – Pointer variables may be subtracted from one another int a, b; int *p = &a, *q = &b; p = p + q ; // Error p = p * q; // Error p = p / q; // Error p = p - q; // OK p = p + 3; p += 1. 6; // Error p %= q; // Error

Arithmetic Operations • When an integer is added to or subtracted from a pointer,

Arithmetic Operations • When an integer is added to or subtracted from a pointer, the new pointer value is changed by the integer times the number of bytes in the data variable the pointer is pointing to – For example, if the pointer p contains the address of a double precision variable and that address is 234567870, then the statement: p = p + 2; // 234567870 + 2 * sizeof(double) would change p to 234567886

Logical Operations • Pointers can be used in comparisons int a[10], *p, *q ,

Logical Operations • Pointers can be used in comparisons int a[10], *p, *q , i; p = &a[2]; q = &a[5]; i = q - p; /* i is 3*/ i = p - q; /* i is -3 */ a[2] = a[5] = 0; i = *p - *q; // i = a[2] – a[5] if (p < q) /* true */ q. . . ; if (p == q). . . ; /* false */ q if (p != q) /* true */ q. . . ; & * p q [0] ? [1] ? [2] ? [3] ? [4] ? [5] ? [6] ? [7] ? [8] ? [9] ?

Pointers and Arrays Array pointer to the initial (0 th) array element a &a[0]

Pointers and Arrays Array pointer to the initial (0 th) array element a &a[0] a[i] *(a+i) &a[i] a + i Example: int a, *p; p=&a; *p = 1; p[0] = 1; a [0] p [1] int a[ 10 ], *p; p = &a[2]; p[0] = 10; p[1] = 10; printf("%d", p[3]); int a[ 10 ], *p; a[2] = 10; a[3] = 10; printf("%d", a[5]); p[0] p[1] p[2] p[3] p[4] p[5] p[6] p[7] [2] [3] [4] [5] [6] [7] [8] [9]

Pointers and Arrays Array pointer to the initial (0 th) array element a &a[0]

Pointers and Arrays Array pointer to the initial (0 th) array element a &a[0] a[i] *(a+i) &a[i] a + i int i; array[10]; for (i = 0; i < 10; i++) { array[i] = …; } 0 a 1 2 3 a+1 a+2 a+3 int *p; int array[10]; for (p = array; p < &array[10]; p++) { *p = …; } These two blocks of code are functionally equivalent

An Array Name is Like a Constant Pointer • Array name is like a

An Array Name is Like a Constant Pointer • Array name is like a constant pointer which points to the first element of the array int a[10], *p, *q; int * const a p = a; /* p = &a[0] */ q = a + 3; /* q = &a[0] + 3 */ a ++; /* Error !!! */

Example int a[10], i; int *p = a; // int *p = &a[0]; for

Example int a[10], i; int *p = a; // int *p = &a[0]; for (i = 0; i < 10; i++) scanf("%d", a + i); // scanf("%d", &a[i]); for (i = 9; i >= 0; --i) printf("%d", *(p + i)); // printf("%d", a[i]); //printf("%d", p[i]); for (p = a; p < &a[10]; p++) printf("%d", *p);

An example int a[10], *p, *q; p = &a[2]; q = p + 3;

An example int a[10], *p, *q; p = &a[2]; q = p + 3; p = q – 1; p++; q--; *p = 123; *q = *p; q = p; printf("%d", *q); & * & p p q q * [0] ? [1] ? [2] ? [3] ? [4] 123 [5] ? [5] 123 [6] ? [7] ? [8] ? [9] ?

An Example int a[10], *p; a++; //Error a--; // Error a += 3; //Error

An Example int a[10], *p; a++; //Error a--; // Error a += 3; //Error p = a; // p = &a[0]; p ++; //OK p--; // Ok P +=3; // Ok

Strings • In C, strings are just an array of characters – Terminated with

Strings • In C, strings are just an array of characters – Terminated with ‘’ character – Arrays for bounded-length strings – Pointer for constant strings (or unknown length) char H e l l str 1[15] = "Hello, world!“; o , char str 1[] char *str 2 H e l l o , w o r l d ! = "Hello, world!"; w o r l d

An Example void copy 1(char * const s 1, const char * const s

An Example void copy 1(char * const s 1, const char * const s 2) { int i; /* counter */ /* loop through strings */ for ( i = 0; ( s 1[ i ] = s 2[ i ] ) != ''; i++ ); /* do nothing in body */ } void copy 2(char *s 1, const char *s 2) { /* loop through strings */ for ( ; ( *s 1 = *s 2 ) != ''; s 1++, s 2++ ); /* do nothing in body */ }

Multi-Dimensional Arrays int a[row][col]; a[row][col] *(*(a + row) + col) scanf(" %d ", &a[0][0])

Multi-Dimensional Arrays int a[row][col]; a[row][col] *(*(a + row) + col) scanf(" %d ", &a[0][0]) scanf(" %d ", a[0]) a[row][col] *(a[row] + col) &a[row][col] a[row] + col printf (" %d ", a[0][0]) printf(" %d ", *a[0]) a a[0][0] a[0] scanf(" %d ", &a[2][2]) scanf(" %d ", a[2]+ 2) a[0] + 2 printf (" %d ", a[2][2]) printf(" %d ", *(a[2] + 2)) a[0] � [0][0] [0][1] [0][2] [0][3] [0][4] [0][5] [0][6] [0][7] [0][8] [0][9] a[1] � [1][0] [1][1] [1][2] [1][3] [1][4] [1][5] [1][6] [1][7] [1][8] [1][9] a[2] � [2][0] [2][1] [2][2] [2][3] [2][4] [2][5] [2][6] [2][7] [2][8] [2][9] a[3] � [3][0] [3][1] [3][2] [3][3] [3][4] [3][5] [3][6] [3][7] [3][8] [3][9] a[4] � [4][0] [4][1] [4][2] [4][3] [4][4] [4][5] [4][6] [4][7] [4][8] [4][9]

Array of Pointers char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" };

Array of Pointers char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" }; suit[0] � H e a r t s suit[1] � D i a m o n d suit[2] � C l u b s suit[3] � S p a d e s

Array of Pointers int a=1, b=2, c=3, d=4; int *k[4] = {&a, &b, &c,

Array of Pointers int a=1, b=2, c=3, d=4; int *k[4] = {&a, &b, &c, &d}; & * k[0] k[1] k[2] k[0] � a 1 k[1] � b k[2] � k[3] a 1 2 b 2 c 3 d 4 printf("%d %d", *k[0], *k[1], *k[2], *k[3]);

Functions • Every C program starts with main() function • Functions could be –

Functions • Every C program starts with main() function • Functions could be – Pre-defined library functions • e. g. , printf, sin, tan – Programmer-defined functions • e. g. , my_printf, area int main() { … }

Functions - Definition Structure • Function 'header' – Return data type (if any) –

Functions - Definition Structure • Function 'header' – Return data type (if any) – Name type function_name (type arg 1, type arg 2 ) { statements; } • Descriptive – Arguments (or parameter list) A function that calculates the product of two numbers • Notice: data type and name • Statements – Variable declaration – Operations – Return value (if any) double product(double x, double y) { double result; result = x * y; return result; }

An Example Function prototype – Like a variable declaration • • • Tells compiler

An Example Function prototype – Like a variable declaration • • • Tells compiler that the function will be defined later Helps detect program errors Note semicolon!! Function definition – See previous slide – Note, NO semicolon Function return – return statement terminates execution of the current function – Control returns to the calling function – if return expression; • • then value of expression is returned as the value of the function call Only one value can be returned this way Function call – – main() is the 'calling function' product() is the 'called function' Control transferred to the function code Code in function definition is executed #include <stdio. h> /* function prototype */ double product(double x, double y); int main() { double var 1 = 3. 0, var 2 = 5. 0; double ans; ans = product(var 1, var 2); printf("var 1 = %. 2 fn" "var 2 = %. 2 fn", var 1, var 2); printf("var 1*var 2 = %gn", ans); return 0; } /* function definition */ double product(double x, double y) { double result; result = x * y; return result; }

Formal and Actual Parameters #include <stdio. h> int cal. Sum(int, int); Formal Parameters /*function

Formal and Actual Parameters #include <stdio. h> int cal. Sum(int, int); Formal Parameters /*function prototype*/ int main(void) Actual Parameters { …. . sum = cal. Sum(num 1, num 2); /* function call */ …. . } int cal. Sum(int val 1, int val 2) /*function header*/ { …… Formal Parameters …… …… }

An Example • If the function requires some arguments to be passed along, then

An Example • If the function requires some arguments to be passed along, then the arguments need to be listed in the ( ) according to the specified order void Calc(int, int double, double char, char int); int main(void) { int a, b; double c; char d; … Calc(a, c, d, b); return (0); } Function Call

Functions that do not return a value • Use the return type of void

Functions that do not return a value • Use the return type of void – void function. Name( Data. Type arg_1, …) – void function. Name( void)

Function Call – An Example #include <stdio. h> //function prototype //global variable declaration int

Function Call – An Example #include <stdio. h> //function prototype //global variable declaration int main(void) { local variable declaration; statements; fn 1( ); fn 2( ); } return (0); 1 2 3 4 void fn 1(void) { local variable declaration; statements; } void fn 2(void) { local variable declaration; statements; return; }

Call by value And Call by reference • Call by value – In this

Call by value And Call by reference • Call by value – In this method, only the copy of variable’s value (copy of actual parameter’s value) is passed to the function. Any modification to the passed value inside the function will not affect the actual value – In all the examples that we have seen so far, this is the method that has been used • Call by reference – In this method, the reference (memory address) of the variable is passed to the function. Any modification passed done to the variable inside the function will affect the actual value – To do this, we need to have knowledge about pointers and arrays

Call by value – An Example #include <stdio. h> int cal. Sum(int, int); /*function

Call by value – An Example #include <stdio. h> int cal. Sum(int, int); /*function protototype*/ int main(void) { int sum, num 1, num 2; printf("Enter two numbers to calculate its sum: n"); scanf("%d%d", &num 1, &num 2); } sum = cal. Sum(num 1, num 2); /* function call */ printf("n %d + %d = %d", num 1, num 2, sum); return(0); int cal. Sum(int val 1, int val 2) /*function definition*/ { int sum; sum = val 1 + val 2; val 2 = 100; Enter two numbers return sum; 4 9 } num 2 4? num 1 9? sum 13 ? val 2 100 4 val 1 9 sum 13 ? to calculate its sum: 4 + 9 = 13 Press any key to continue

Call by reference #include <stdio. h> void Cal. By. Val(int a, int b) {

Call by reference #include <stdio. h> void Cal. By. Val(int a, int b) { a = 0; b = 10; } void Cal. By. Ref(int *a, int *b) // Cal. By. Ref(int *p, int *q) { *a = 0; *b = -5; // a = 0; !!!! } int main(void) { int a = 1, b = 5; printf("Before cal Cal. By. Val: a = %d, b = %dn", a, b); Cal. By. Val(a, b); printf("After cal Cal. By. Val: a = %d, b = %dn", a, b); printf("Before cal Cal. By. Ref: a = %d, b = %dn", a, b); Cal. By. Ref(&a, &b); printf("After cal Cal. By. Ref: a = %d, b = %dn", a, b); getch(); return 0; /* Exit program. */ } b 10 5 Cal. By. Val a b 1 0 Cal. By. Ref b -5 5 main a 1 0 a

Pointers and Arrays • Recall that the value of an array name is also

Pointers and Arrays • Recall that the value of an array name is also an address void main() { int x[10]; Re. Order(x); // Re. Order(&x); } void Re. Order(int *x) { int i, j, t; for(i = 0; i < 9; i++) for(j = i + 1; i < 10; ++j) if(x[i] < x[j]) { t = x[i]; x[i] = x[j]; x[j] = t; } }

Organizing Multi-File Programs • A large C program should be divided into multiple files

Organizing Multi-File Programs • A large C program should be divided into multiple files // main. c #include <stdio. h> void Test() { // … } int main() { // … return 0; } // math. c double math. Var; double sin() { double temp. Sin; // … return temp. Sin; }

Identifiers and Scope • Identifier – The name of a variable, function, label, etc.

Identifiers and Scope • Identifier – The name of a variable, function, label, etc. • int my_var 1; /* a variable */ • pow_table(); /* a function */ • start: /* a label */ • Question: – Does it make a difference where in a program an identifier is declared? YES! --> concept of ‘scope’

Scope of Identifiers • Scope of a declaration of an identifier – The region

Scope of Identifiers • Scope of a declaration of an identifier – The region of the program that the declaration is active (i. e. , can access the variable, function, label, etc. ) • Five types of scope: – Program (global scope) – File – Function prototype – Function – Block ("between the { } scope")

Scope of Identifiers - Program Scope • Program (global) scope – if declared outside

Scope of Identifiers - Program Scope • Program (global) scope – if declared outside of all functions – "Visible" to all functions from point of declaration – Visible to functions in other source files – Use only when necessary and then very carefully!! – If there exist a local variable and a global variable with the same name, the compiler will refer to the local variable #include <stdio. h> int a = 10; double product(double x, double y); int main() { double var 1 = 3. 0, var 2 = 5. 0; double ans; a = 10 ans = product(var 1, var 2); // … a = 20 } /* function definition */ double product(double x, double y) { double result; a = 20; result = x * y; return result; }

An Example // File name: main. c #include <stdio. h> int a = 10;

An Example // File name: main. c #include <stdio. h> int a = 10; // File name: Extern. File. c extern int a = 10; /* function definition */ void Test. Extern() { // … a = 90; // … } /* function definition */ double product(double x, double y) { double result; // … a = 70; return result; } int main() { a = 80; }

Scope of Identifiers - File Scope • File scope – Keyword static • Makes

Scope of Identifiers - File Scope • File scope – Keyword static • Makes variable a ‘visible’ only within this source file – Use file scope to avoid naming conflict if multiple source files are used #include <stdio. h> static int a = 10; double product(double x, double y); int main() { double var 1 = 3. 0, var 2 = 5. 0; double ans; ans = product(var 1, var 2); // … } /* function definition */ double product(double x, double y) { double result; result = x * y; return result; }

An Example // File name: main. c #include <stdio. h> static int a =

An Example // File name: main. c #include <stdio. h> static int a = 10; // File name: Extern. File. c extern int a = 10; /* function definition */ void Test. Extern() { // … a = 90; // … } /* function definition */ double product(double x, double y) { double result; // … a = 70; return result; } int main() { a = 80; }

Scope of Identifiers - Function Prototype Scope • Function prototype scope – Identifiers x

Scope of Identifiers - Function Prototype Scope • Function prototype scope – Identifiers x and y are not visible outside the prototype – Thus, names in the prototype do not have to match names in the function definition • MUST match types, however! #include <stdio. h> double product(double x, double y); int main() { int a = 10; double var 1 = 3. 0, var 2 = 5. 0; double ans; ans = product(var 1, var 2); printf("var 1 = %. 2 fn" "var 2 = %. 2 fn", var 1, var 2); printf("var 1*var 2 = %gn", ans); } /* function definition */ double product(double A, double B) { double result; result = A * B; return result; }

Scope of Identifiers - Function Scope • Function scope – Active from the beginning

Scope of Identifiers - Function Scope • Function scope – Active from the beginning to the end of a function #include <stdio. h> int main() { int a; // … return 0; } int Function. Scope. Test() { int b; // … return 0; }

Scope of Identifiers - Block Scope • Block (local) scope – A block is

Scope of Identifiers - Block Scope • Block (local) scope – A block is a series of statements enclosed in braces {} – The identifier scope is active from the point of declaration to the end of the block ( } ) – Nested blocks can both declare the same variable name and not interfere #include <stdio. h> double product(double x, double y); int main() { int a = 10; double var 1 = 3. 0, var 2 = 5. 0; double ans; ans = product(var 1, var 2); // … } /* function definition */ double product(double x, double y) { double result; // a = 60; Error result = x * y; return result; }

An Example #include <stdio. h> int a = 10; int f 1() { int

An Example #include <stdio. h> int a = 10; int f 1() { int a; a = 70; { int a; a = 100; } return a; } void main() { a = 80; f 1(); } a=? a = 70 a = 100 a = 70 a = 10 a = 80

Storage Classes • Refers to the lifetime of a variable • Local variables only

Storage Classes • Refers to the lifetime of a variable • Local variables only exist within a function by default. When calling a function repeatedly, we might want to – Start from scratch – reinitialize the variables • The storage class is ‘auto’ auto – Continue where we left off – remember the last value • The storage class is ‘static’ static • Another two storage classes (seldomly used) – register (ask to use hardware registers if available) – extern (global variables are external)

Auto storage class • Variables with automatic storage duration are created when the block

Auto storage class • Variables with automatic storage duration are created when the block in which they are declared is entered, exist when the block is active and destroyed when the block is exited. • The keyword auto explicitly declares variables of automatic storage duration. It is rarely used because when we declare a local variable, by default it has class storage of type auto. – int a, b; // is the same as – auto int a, b;

Static storage class • However the static keyword can be applied to a local

Static storage class • However the static keyword can be applied to a local variable so that the variable still exist even though the program has gone out of the function. As a result, whenever the program enters the function again, the value in the static variable still holds

Auto - Example #include <stdio. h> void auto_example(void); int main(void) { int i; printf("Auto

Auto - Example #include <stdio. h> void auto_example(void); int main(void) { int i; printf("Auto example: n"); auto_example( ); return(0); } void auto_example(void) { auto int num = 1; printf(" %dn", num); num = num + 2; } Auto example: 1 1 1 Press any key to continue

Static - Example #include <stdio. h> void auto_example(void); int main(void) { int i; printf("Static

Static - Example #include <stdio. h> void auto_example(void); int main(void) { int i; printf("Static example: n"); static_example( ); return(0); } void static_example(void) { static int num = 1; printf(" %dn", num); num = num + 2; } Static example: 1 3 5 Press any key to continue

Recursion • Recursion is a technique that solves a problem by solving a smaller

Recursion • Recursion is a technique that solves a problem by solving a smaller problem of the same type • A recursive function is a function invoking itself, either directly or indirectly – Recursion: A → B → C → D → A • Concept of recursive function (generally): – A recursive function is called to solve a problem – The function only knows how to solve the simplest case of the problem. When the simplest case is given as an input, the function will immediately return with an answer – However, if a more complex input is given, a recursive function will divide the problem into 2 (or more) pieces: a part that it knows how to solve and another part that it does not know how to solve if (stopping case) solve it else reduce the problem using recursion

Recursion solution of xy #include <stdio. h> double Xpower. Y(double, int); int main(void) {

Recursion solution of xy #include <stdio. h> double Xpower. Y(double, int); int main(void) { double power, x; int y; printf("Enter the value of x and y: n"); scanf("%lf%d", &x, &y); power = Xpower. Y(x, y); printf("%. 2 f to the power of %d is %. 2 fnn", x, y, power); return(0); Enter the value of x and y: } 2 double Xpower. Y(double x, int y) Xpower. Y 3 2. 00 to the power of 3 is 8. 00 { Press any key to continue if (y ==1) return x; else return x * Xpower. Y(x, Xpower. Y y-1); }

Recursive Steps of xy #include <stdio. h> double Xpower. Y(double, int); int main(void) 2

Recursive Steps of xy #include <stdio. h> double Xpower. Y(double, int); int main(void) 2 { double power, x; int y; printf("Enter the value of x and y: n"); scanf("%lf%d", &x, &y); 2*2 power = Xpower. Y(x, y); printf("%. 2 f to the power of %d is %. 2 fnn", x, y, power); return(0); } double Xpower. Y(double x, int y) Xpower. Y 2*4 { if (y ==1) return x; else 2*8 return x * Xpower. Y(x, Xpower. Y y-1); } x = 2; y = 2; return x; x = 2; y = 2; x * Xpower. Y(2, 1) x = 2; y = 3; x * Xpower. Y(2, 2) x = 2; y = 4; x * Xpower. Y(2, 3)

Pointer to Function #include <stdio. h> void f 1(float a){ printf("F 1 %g", a);

Pointer to Function #include <stdio. h> void f 1(float a){ printf("F 1 %g", a); } void f 2(float a){ printf("F 2 %g", a); } int main(){ void (*ptr. F)(float a); ptr. F = f 1; ptr. F(12. 5); ptr. F = f 2; ptr. F(12. 5); getch(); return 0; } A function pointer is defined in the same way as a function prototype, but the function name is replaced by the pointer name prefixed with an asterisk and encapsulated with parenthesis Example: int (*fptr)(int, char) fptr = some_function; (*ftpr)(3, 'A'); some_function(3, 'A');

Array of Functions #include<stdio. h> void func 1() { printf("Function 1 Calledn"); } void

Array of Functions #include<stdio. h> void func 1() { printf("Function 1 Calledn"); } void func 2() { printf("Function 2 Calledn"); } void func 3() { printf("Function 3 Calledn"); } int main(int argc, char *argv[]) { void (*ptr[3]) () = {func 1, func 2, func 3}; int k = 0; for(k = 0; k < 3; k++) ptr[k](); getch(); return 0; }

Passing Arrays to Functions #include <stdio. h> void display(int a) { printf("%d", a); }

Passing Arrays to Functions #include <stdio. h> void display(int a) { printf("%d", a); } int main() { int c[] = {2, 3, 4}; display(c[2]); //Passing array element c[2] only return 0; }

Passing Arrays to Functions #include <stdio. h> float average(float a[], int count); // float

Passing Arrays to Functions #include <stdio. h> float average(float a[], int count); // float average(float *a, int count) int main(){ float avg, c[]={23. 4, 55, 22. 6, 3, 40. 5, 18}; avg=average(c, 6); /* Only name of array is passed as argument */ printf("Average age=%. 2 f", avg); return 0; } float average(float a[], int count){ // float average(float int I; float avg, sum = 0. 0; for(I = 0; I < count; count ++i) sum += a[i]; avg = (sum / 6); return avg; } *a) void func (int* x); /* this is a pointer */ void func (int x[]); /* this is a pointer */ void func (int x[10]); /* this is a pointer */

Passing Arrays to Functions #include <stdio. h> void f 1(float *a) { a[1] =

Passing Arrays to Functions #include <stdio. h> void f 1(float *a) { a[1] = 100; } void f 2(float a[]){ a[2] = 200; } void print. Arrat(float a[]) { int i = 0; for(; i < 6; i++) printf("%g ", a[i]); } int main(){ float c[]={23. 4, 55, 22. 6, 3, 40. 5, 18}; f 1(c); print. Arrat(c); puts(""); f 2(c); print. Arrat(c); getch(); return 0; } Passing Array By Reference 23. 4 55 22. 6 3 40. 5 18 23. 4 100 200 3 40. 5 18

Passing 2 D, 3 D, … Array to Functions • Only the first dimension

Passing 2 D, 3 D, … Array to Functions • Only the first dimension may be omitted – int m[5][7]; – func(m); – void func(int a[5][7]) {. . . } – void func(int a[][7]) {. . . }

Allocating Memory for a Pointer // The following program is wrong! // This one

Allocating Memory for a Pointer // The following program is wrong! // This one is correct: #include <stdio. h> int main() { int *p; Don’t { int *p; scanf("%d", p); int a; return 0; p = &a; } scanf("%d", p); return 0; }

malloc • Prototype: void *malloc(size_t size); #include <stdlib. h> – function returns the address

malloc • Prototype: void *malloc(size_t size); #include <stdlib. h> – function returns the address of the first byte – programmers responsibility to not lose the pointer • Example: Key int *ptr; ptr = (int *)malloc(sizeof(int)); // new allocation 10 ptr Memory 0 previously allocated 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

free • Prototype: void free(void *ptr) – releases the area pointed to by ptr

free • Prototype: void free(void *ptr) – releases the area pointed to by ptr – ptr must not be null #include <stdlib. h> • trying to free the same area twice will generate an error 2 p 2 5 p 1 initial memory 2 p 2 0 1 2 3 4 5 6 7 free(p 1); NULL p 1 after free 0 1 2 3 4 5 6 7 Key allocated memory free memory

Allocating Memory for a Pointer • There is another way to allocate memory so

Allocating Memory for a Pointer • There is another way to allocate memory so the pointer can point to something: #include <stdio. h> #include <stdlib. h> int main(){ int *p; p = (int *) malloc( sizeof(int) ); ) /* Allocate 4 bytes */ scanf("%d", p); printf("%d", *p); //. . free(p); /* This returns the memory to the system*/ /* Important !!! */ }

Allocating Memory for a Pointer • You can use malloc and free to dynamically

Allocating Memory for a Pointer • You can use malloc and free to dynamically allocate and release the memory int *p; p = (int *) malloc(1000 * sizeof(int) ); ) for(i=0; i<1000; i++) p[i] = i; p[999]=3; p[1000]=3; /* Wrong! */ free(p); p[0]=5; /* Wrong! */

Structures • Structures – Be able to use compound data structures in programs •

Structures • Structures – Be able to use compound data structures in programs • Unions – Be able to share storage space of their members • Bit fields Structures – Be able to do simple bit-vector manipulations • Enumerations – Be able to use compound symbolic constants

User Defined Data Types (typedef) • The C language provides a facility called typedef

User Defined Data Types (typedef) • The C language provides a facility called typedef for creating synonyms for previously defined data type names. • For example, the declaration: typedef int Length; makes the name Length a synonym (or alias) alias for the data type int • The data type name Length can now be used in declarations in exactly the same way that the data type int can be used: Length a, b, len ; Length numbers[10] ; typedef char String[50]; typedef int Array[10]; String name; Array ages;

Structures (struct) • Structures—sometimes referred to as aggregates—are collections Structures aggregates of related variables

Structures (struct) • Structures—sometimes referred to as aggregates—are collections Structures aggregates of related variables under one name • Structures may contain variables of many different data types—in types contrast to arrays that contain only elements of the same data type • Structures are commonly used to define records to be stored in files • Pointers and structures facilitate the formation of more complex data structures such as linked lists, lists queues, queues stacks and trees • Structures are derived data types—they are constructed using types objects of other types

Declaring Structures (struct) • The name "employee" is called a structure tag • Variables

Declaring Structures (struct) • The name "employee" is called a structure tag • Variables declared within the braces of the structure definition are the structure’s members struct employee { { char first. Name[ 20 ]; char last. Name[ 20 ]; int age; char gender; int age; double hourly. Salary; char gender; double hourly. Salary; } Ali, Sara, emp. DTS[20]; }; struct employee Reza, struct employee Ali, *emp; emp[10]; struct { char first. Name[ 20 ]; char last. Name[ 20 ]; int age; char gender; double hourly. Salary; } Ali;

Declaring Structures (struct) • Often, typedef is used in combination with struct to declare

Declaring Structures (struct) • Often, typedef is used in combination with struct to declare a synonym (or an alias) for a structure: typedef struct { char first. Name[ 20 ]; char last. Name[ 20 ]; int age; char gender; double hourly. Salary; } employee; /* The "alias" employee Ali; /* Create a struct variable */ struct employee { char first. Name[ 20 ]; char last. Name[ 20 ]; int age; char gender; double hourly. Salary; } Ali, Sara, emp. DTS[20]; struct employee Reza, *emp;

Declaring Structures (struct) • Members of the same structure type must have unique names,

Declaring Structures (struct) • Members of the same structure type must have unique names, but two different structure types may contain members of the same name without conflict struct employee { char Name[ 20 ]; // Error!!! int age; char gender; double hourly. Salary; } Ali, Sara, emp. DTS[20]; struct employee Reza, *emp; struct Student { char Name[ 20 ]; // OK int age; char gender; }; struct Student Ce 40153[80]; • Each structure definition must end with a semicolon

Declaring Structures (struct) • A structure cannot contain an instance of itself • For

Declaring Structures (struct) • A structure cannot contain an instance of itself • For example, a variable of type struct employee cannot be declared in the definition for struct employee A pointer to struct employee, however, may be included struct employee 2 { // … double hourly. Salary; struct employee 2 person; /* ERROR */ struct employee 2 *e. Ptr; /* pointer */ }; • A structure containing a member that is a pointer to the same structure type is referred to as a selfreferential structure

Declaring Structures (struct) • The structure tag name is optional struct { char first.

Declaring Structures (struct) • The structure tag name is optional struct { char first. Name[ 20 ]; char last. Name[ 20 ]; int age; char gender; double hourly. Salary; } Ali; • If a structure definition does not contain a structure tag name, variables of the structure type may be declared only in the structure definition—not in a separate declaration

Memory layout struct COST { int amount; char currency_type[2]; } struct PART { char

Memory layout struct COST { int amount; char currency_type[2]; } struct PART { char id[2]; struct COST cost; int num_avail; } id currency_type amount num_avail cost • Here, the system uses 4 -byte alignment of integers, so amount and num_avail must be aligned Four bytes wasted for each structure!

Memory layout struct COST { int amount; char currency_type[2]; } struct PART { }

Memory layout struct COST { int amount; char currency_type[2]; } struct PART { } struct COST cost; char id[2]; int num_avail; currency_type amount cost • Implementation dependent!!! id num_avail

Accessing Struct Members • Individual members of a struct variable may be accessed using

Accessing Struct Members • Individual members of a struct variable may be accessed using the structure member operator (the dot, ". "): my. Emp. first. Name ; struct employee { employee. first. Name; // Error char first. Name[ 20 ]; // … } my. Emp; • Or , if a pointer to the struct has been declared and initialized employee *emp = &my. Emp ; – by using the structure pointer operator : emp -> first. Name; // arrow operator – which could also be written as: (* emp). first. Name;

An Example - Initialization //Create a struct but don’t reserve space struct personal {

An Example - Initialization //Create a struct but don’t reserve space struct personal { long id; // student ID float gpa; // grade point average }; struct identity { char First. Name[30]; char Last. Name[30]; unsigned age; struct personal person; }; struct identity js = {"Joe", "Smith", 25}, *ptr = &js ; js. person. id = 123456789 ; js. person. gpa = 3. 4 ; jsstrcpy(js. First. Name, =js. {"Joe", "Smith", "Joe"); 9, 10} strcpy(. id 25, Error personal printf ("%s %s %d %ld %fn", js. First. Name, js. Last. Name, js. age, js. person. id, js. person. gpa) ; printf ("%s %s %d %ld %fn", ptr->First. Name, ptr->Last. Name, ptr->age, ptr->person. id, ptr->person. gpa) ;

An Example - Assignment //Create a struct but don’t reserve space struct personal {

An Example - Assignment //Create a struct but don’t reserve space struct personal { long id; // student ID float gpa; // grade point average }; struct identity { char First. Name[30]; char Last. Name[30]; unsigned age; struct personal person; }; struct identity js = {"Joe", "Smith", 25} oj ; js. person. id = 123456789 ; js. person. gpa = 3. 4 ; oj = js; printf ("%s %s %d %ld %fn", oj. First. Name, oj. Last. Name, oj. age, js. person. id, oj. person. gpa) ; printf ("%s %s %d %ld %fn", ptr->First. Name, ptr->Last. Name, ptr->age, ptr->person. id, ptr->person. gpa) ;

Arrays of Structures struct identity sharif. C 40153[80] = {"omid", "Jafarinezhad", 14, 9140153, 20,

Arrays of Structures struct identity sharif. C 40153[80] = {"omid", "Jafarinezhad", 14, 9140153, 20, struct identity //Create a struct but don’t reserve space "Samad", "Shekarestani", 90, 2222222, 20} ; { struct personal strcpy(sharif. C 40153[2]. First. Name, "Khaje Nezam"); strcpy(sharif. C 40153[2]. Nezam" char First. Name[30]; { strcpy(sharif. C 40153[2]. Last. Name, "Shekarestani"); strcpy(sharif. C 40153[2]. "Shekarestani" char Last. Name[30]; long id; // student ID sharif. C 40153[2]. age = 100; unsigned age; float gpa; // grade point average sharif. C 40153[2]. person. id = 1111; struct personal person; }; sharif. C 40153[2]. person. gpa = 20; } students[4]; First. Name Last. Name age students[0] omid Jafarinezhad Students[1] Samad students[2] Khaje Nezam students[3] person id gpa 14 9140153 20 Shekarestani 90 2222222 20 Shekarestani 100 1111 20

Pointers to Structures void create_date 2(Date *d, Date create_date 1(int month, int day, int

Pointers to Structures void create_date 2(Date *d, Date create_date 1(int month, int day, int year) Pass-by-reference int year) { { Date d; d->month = month; d->day = day; d. month = month; d->year = year; d. day = day; } d. year = year; return (d); } Date today; Copies date today = create_date 1(9, 4, 2008); create_date 2(&today, 9, 4, 2008);

Pointers to Structures void create_date 2(Date *d, int month, int day, int year) {

Pointers to Structures void create_date 2(Date *d, int month, int day, int year) { d->month = month; d->day = day; d->year = year; } void foo(void) { Date today; create_date 2(&today, 9, 4, 2008); } 0 x 30 A 8 year: 2008 0 x 30 A 4 day: 4 0 x 30 A 0 month: 9 0 x 3098 d: 0 x 1008 today. year: 2008 0 x 1004 today. day: 4 0 x 1000 today. month: 9 0 x 1000

Compression of Structures • Structures may not be compared using operators == and !=,

Compression of Structures • Structures may not be compared using operators == and !=, because structure members are not necessarily stored in consecutive bytes of memory struct a { int a; // OK int b; }; struct a b, c; b. a = 10; b. b = 30; c = b; if(c == b) // Error

Enumeration • Enumeration is a user-defined data type. It is defined using the keyword

Enumeration • Enumeration is a user-defined data type. It is defined using the keyword enum and the syntax is: enum tag_name {name_0, …, name_n} ; • The tag_name is not used directly The names in the braces are symbolic constants that take on integer values from zero through n. As an example, the statement: enum colors { red, yellow, green } ; – creates three constants. red is assigned the value 0, yellow is assigned 1 and green is assigned 2

Enumeration • Values in an enum start with 0, unless specified otherwise, otherwise and

Enumeration • Values in an enum start with 0, unless specified otherwise, otherwise and are incremented by 1 • The identifiers in an enumeration must be unique • The value of each enumeration constant of an enumeration can be set explicitly in the definition by assigning a value to the identifier • Multiple members of an enumeration can have the same constant value • Assigning a value to an enumeration constant after it has been defined is a syntax error • Use only uppercase letters enumeration constant names. This makes these constants stand out in a program and reminds you that enumeration constants are not variables

An Example /* enumeration constants represent months of the year */ enum months {JAN

An Example /* enumeration constants represent months of the year */ enum months {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC }; enum months month; /* initialize array of pointers */ const char *month. Name[] = { "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", /* loop through months */ for (month = JAN; month <= DEC; month++ ) { printf( "%2 d%11 sn", month. Name[month] ); }

Unions • A union is a derived data type—like a structure—with members that share

Unions • A union is a derived data type—like a structure—with members that share the same storage space • For different situations in a program, some variables may not be relevant, but other variables are—so a union shares the space instead of wasting storage on variables that are not being used • The members of a union can be of any data type • The number of bytes used to store a union must be at least enough to hold the largest member • Only one member, and thus one data type, can be referenced at a time

Unions representation union my. Data. Union { int i; char c; float f; }

Unions representation union my. Data. Union { int i; char c; float f; } u 1, u 2; union my. Data. Union u 3; u 1. i = 4; u 1. c = ’a’; u 2. i = 0 x. DEADBEEF; c i f

Unions • The operations that can be performed on a union are the following:

Unions • The operations that can be performed on a union are the following: – assigning a union to another union of the same type – taking the address (&) of a union variable – accessing union members using the structure member operator and the structure pointer operator • Unions may not be compared using operators == and != for the same reasons that structures cannot be compared

Unions • In a declaration, a union may be initialized with a value of

Unions • In a declaration, a union may be initialized with a value of the same type as the first union member union a { int a; // OK char b[4]; }; union a b = {10}; printf("%d", b. a);

Unions • A union value doesn’t "know" which case it contains union An. Elt

Unions • A union value doesn’t "know" which case it contains union An. Elt { int i; char c; } elt 1, elt 2; elt 1. i = 4; elt 2. c = ’a’; elt 2. i = 0 x. DEADBEEF; if (elt 1 currently has a char) … ? How should your program keep track whether elt 1, elt 2 hold an int or a char? ? Basic answer: Another variable holds that info

Tagged Unions • Tag every value with its case enum Union_Tag {IS_INT, IS_CHAR}; struct

Tagged Unions • Tag every value with its case enum Union_Tag {IS_INT, IS_CHAR}; struct Tagged. Union { enum Union_Tag tag; union { int i; char c; } data; }; Enum must be external to struct, so constants are globally visible Struct field must be named

Bit-field Structures • C enables you to specify the number of bits in which

Bit-field Structures • C enables you to specify the number of bits in which an unsigned or int member of a structure or union is stored • This is referred to as a bit field • Bit fields enable better memory utilization by storing data in the minimum number of bits required • Bit field members must be declared as int or unsigned • A bit field is declared by following an unsigned or int member name with a colon (: ) and an integer constant representing the width of the field (i. e. , the number of bits in which the member is stored)

Bit-field Structures • Notice that bit field members of structures are accessed exactly as

Bit-field Structures • Notice that bit field members of structures are accessed exactly as any other structure member struct Flags { int unsigned int } foo; foo. f 1 = -2; foo. f 2 = 1; foo. f 3 = 2; f 1: 3; f 2: 1; f 3: 2; f 3 … 8 bit … … … 1 f 2 0 • Padded to be an integral number of words – Placement is compiler-specific 1 f 1 1 1 0

Unnamed Bit-field struct example { unsigned a : 13; unsigned : 19; }; unsigned

Unnamed Bit-field struct example { unsigned a : 13; unsigned : 19; }; unsigned b : 4; • uses an unnamed 19 -bit field as padding—nothing can be stored in those 19 bits • An unnamed bit field with a zero width is used to align the next bit field on a new storage-unit boundary • For example, the structure definition struct example { unsigned a : 13; unsigned : 0; }; unsigned b : 4; uses an unnamed 0 -bit field to skip the remaining bits (as many as there are) of the storage unit in which a is stored and to align b on the next storage-unit boundary

An Example - disk drive controller • Frequently device controllers (e. g. disk drives)

An Example - disk drive controller • Frequently device controllers (e. g. disk drives) and the operating system need to communicate at a low level. Device controllers contain several registers which may be packed together in one integer

An Example - disk drive controller struct DISK_REGISTER { unsigned ready: 1; unsigned error_occured:

An Example - disk drive controller struct DISK_REGISTER { unsigned ready: 1; unsigned error_occured: 1; unsigned disk_spinning: 1; unsigned write_protect: 1; unsigned head_loaded: 1; unsigned error_code: 8; unsigned track: 9; unsigned sector: 5; unsigned command: 5; }; struct DISK_REGISTER *disk_reg = (struct DISK_REGISTER *) DISK_REGISTER_MEMORY; /* Define sector and track to start read */ disk_reg->sector = new_sector; disk_reg->track = new_track; disk_reg->command = READ; /* wait until operation done, ready will be true */ while ( ! disk_reg->ready ) ; /* check for errors */ if (disk_reg->error_occured) { /* interrogate disk_reg->error_code for error type */ switch (disk_reg->error_code). . . }