KEMBAR78
C Lectures | PDF | Integer (Computer Science) | Compiler
0% found this document useful (0 votes)
20 views149 pages

C Lectures

The document provides an overview of basic computer concepts, types of programming languages, and the history of the C programming language. It covers elements of a typical C program, including data types, input/output statements, variable declarations, and scopes. Additionally, it explains operators, decision-making statements, and the use of keywords in C programming.

Uploaded by

202474018
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views149 pages

C Lectures

The document provides an overview of basic computer concepts, types of programming languages, and the history of the C programming language. It covers elements of a typical C program, including data types, input/output statements, variable declarations, and scopes. Additionally, it explains operators, decision-making statements, and the use of keywords in C programming.

Uploaded by

202474018
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 149

Computer Programming I – C

Dr. Sami AL-MAQTARI


Basic computer concepts
• Input devices:
• Keyboard, mouse, touch-screen, …etc.
• Output devices:
• Screen, printer, loud speakers, ...etc.
• Central Processing Unit (CPU)
• Processing digital data
Central Processing Unit
• Memory (CPU)
• Data storage
Input Output
devices devices

Memory

2
The different types of programming languages
• Machine Code
• Binary representation of instructions and data.
• Machine specific.
• Difficult to read, understand, and maintain.
• Assembly language
• Symbolic English representation of machine code.
• Easier to write than machine code.
• Still not easy to write and maintain.
• High-Level Languages (HLL)
• Closer to human language.
• More portable and easier to understand and maintain.

3
High-Level Languages types
• Compiled languages
• Source code is translated into machine code (executable file) using
compilers.
• Pros: The final code can be executed directly on the target machine.
• Cons: Low portability, need to be recompiled to be executed on a
different machine.
• Interpreted (script) languages
• Source code is translated on the fly into machine code using
interpreters.
• Pros: High portability, the program can be run on a new machine using
a proper interpreter.
• Cons: Slow to execute compared to compiled code.

4
History of the C programming language
• The base or father of programming languages is 'ALGOL.' It was
first introduced in 1960.
• Introduced the concept of structured programming to the developer
community.
• In 1967, a new computer programming language was
announced called as 'BCPL' which stands for Basic Combined
Programming Language.
• Designed and developed by Martin Richards, especially for writing
system software. This was the era of programming languages.
• In 1970 a new programming language called 'B' was
introduced by Ken Thompson that contained multiple features
of 'BCPL.’
• Created using UNIX operating system at AT&T and Bell Laboratories.
Both the 'BCPL' and 'B' were system programming languages.

6
History of the C programming language
• In 1972, computer scientist Dennis Ritchie created
a new programming language called 'C' at the Bell
Laboratories.
• It was created from 'ALGOL', 'BCPL' and 'B'
programming languages.
• 'C' programming language contains all the features of
these languages and many more additional concepts
that make it unique from other languages.
• 'C' is a powerful programming language which is
strongly associated with the UNIX operating system.
Even most of the UNIX operating system is coded in 'C’.
• Initially 'C' programming was limited to the UNIX
operating system.
• Today 'C' runs under a variety of operating systems and
hardware platforms.
• To assure that 'C' language will remain standard,
American National Standards Institute (ANSI) defined a
commercial standard for 'C' language in 1989. Later, it
was approved by the International Standards
Organization (ISO) in 1990. 'C' programming language
is also called as 'ANSI C'.

7
Elements of a typical C program development
environment
• Preprocessing statements #include <stdio.h>

• The main function // The main function


int main() {
• Function call statement
printf("Hello, World!");
• Return statement return 0;
}
• Comments

8
Simple input and output statements
• A normal program receives input data, process it, and give an output.
• Data received are stored in variables.
• C is a typed language, i.e. variables should be declared before use.
• Declaring variables should be in the beginning of the function before any use of them.
• C is a case-sensitive language (e.g. number, Number, and NUMBER are different variables)
• scanf() is used to read values from keybord.
• printf() is used to display results on screen.
• Use printf() to prompt user for values.
• Do not forget the return statement.
#include <stdio.h>

int main() {
int x;
printf("Enter an integer: ");
scanf("%d", &x);
printf("You have entered %d", x);
return 0;
}

9
Fundamental data types
• Characters (letters and symbols) char

• Integer numbers
• Shorts integers short or short int
int
• Normal integers long or long int
• Long integers
• Real numbers
• Single precision reals float
double
• Double precision reals long double
• Long doubles
• Modifiers
• Unsigned short integers unsigned short or unsigned short int
unsigned int
• Unsigned integers unsigned long or unsigned long int
• Unsigned long integers

10
printf() and scanf() conversion specification
Format Specifier Type Format Specifier Type

%c Character %lu Unsigned int or unsigned


long
%d Signed integer
%lli or %lld Long long
%e or %E Scientific notation of floats
%llu Unsigned long long
%f Float values
%o Octal representation
%g or %G Similar as %e or %E
%p Pointer
%hi Signed integer (short)
%s String
%hu Unsigned Integer (short)
%u Unsigned int
%i Unsigned integer
%x or %X Hexadecimal
%l or %ld or %li Long representation
%lf Double %n Prints nothing
%Lf Long double %% Prints % character

12
Adding two numbers program
/* add.c
Addition program */
#include <stdio.h>

/* function main begins program execution */


int main() {
int integer1; /* first number to be input by user */
int integer2; /* second number to be input by user */
int sum; /* variable in which sum will be stored */

printf( "Enter first integer\n" ); /* prompt */


scanf( "%d", &integer1 ); /* read an integer */
printf( "Enter second integer\n" ); /* prompt */
scanf( "%d", &integer2 ); /* read an integer */
sum = integer1 + integer2; /* assign total to sum */
printf( "Sum is %d\n", sum ); /* print sum */

return 0; /* indicate that program ended successfully */


} /* end function main */

13
Computer memory concepts
• Each variable has four characters:
• ID (name)
• Contains letters and digits
• Start with a letter or underscore
• ?, !, %, +, *, … are forbidden
• Type
• Value
• Location (address in the memory)

14
Arithmetic Operators

15
Precedence of arithmetic operators

16
Precedence of arithmetic operators (cont.)

17
Equality and Relational Operators

18
Simple decision making statements
#include <stdio.h>

int main( void ) {


int num1; int num2;
printf("Enter two integers, and I will tell you\n");
printf("the relationships they satisfy: ");
scanf("%d%d", &num1, &num2);

if ( num1 == num2 ) printf("%d is equal to %d\n", num1, num2);


if ( num1 != num2 ) printf("%d is not equal to %d\n", num1, num2);

if ( num1 > num2 )


printf("%d is greater than %d\n", num1, num2);
if ( num1 < num2 )
printf("%d is less than %d\n", num1, num2);

if ( num1 >= num2 ) {


printf("%d is greater than or equal to %d\n", num1, num2);
}
if ( num1 <= num2 ) {
printf("%d is less than or equal to %d\n", num1, num2);
}
return 0;
}
19
Precedence and associativity of the operators

20
C language keywords

21
Expressions: datatypes and more
• Variables’ declaration
𝑡𝑦𝑝𝑒 𝑣𝑎𝑟𝑖𝑎𝑏𝑙𝑒_𝑙𝑖𝑠𝑡;
or
𝑡𝑦𝑝𝑒 𝑣𝑎𝑟1 = 𝑣𝑎𝑙𝑢𝑒1 , 𝑣𝑎𝑟2 = 𝑣𝑎𝑙𝑢𝑒2 … ;
Where:
• 𝑡𝑦𝑝𝑒 must be a valid data type plus any modifiers, and
• 𝑣𝑎𝑟𝑖𝑎𝑏𝑙𝑒 − 𝑙𝑖𝑠𝑡 may consist of one or more identifier names separated
by commas.
int i, j, l;
short int si;
unsigned int ui;
double balance, profit, loss;

22
Where Variables Are Declared?
• Local Variables
• Variables that are declared inside a function are called local variables
(automatic variables).
• Used only by statements that are inside the block in which the variables are
declared.
• Exist only while the block of code in which they are declared is executing.
i.e. a local variable is created upon entry into its block and destroyed upon
exit.
• A variable declared within one code block has no bearing on or relationship
to another variable with the same name declared within a different code
block.
• Most programmers declare all the variables used by a function immediately
after the function's opening curly brace and before any other statements
(obligatory before C99). However, you may declare local variables within
any code block. The block defined by a function is simply a special case.

23
Examples of Local Variables
void func1(void) { int main() {
int x; int x;
x = 10; x = 10;
} if (x == 10) {
void func2(void) { int x;
int x; x = 99;
x = -199; printf("Inner x: %d\n", x);
} }
printf("Outer x: %d\n", x);
int main() { return 0;
int t; }
printf("Enter an integer: ");
scanf("%d", &t); void f() {
if (t==1) { int i;
char c = 'T'; i = 10;
printf("%c\n", c); int j; // Error before C99
} j = 20;
printf("%d\n", t); }
}

24
Where Variables Are Declared? (cont.)
• Formal Parameters
• If a function is to use arguments, it must declare variables that will
accept the values of the arguments.
• They behave like any other local variables inside the function.
• Their declarations occur after the function name and inside
parentheses.
• They receive the value of the arguments passed to the function.
• They are destroyed upon exit from the function.

25
Example of Formal Parameters

void addAndPrint(int first, int second) {


int sum;
sum = first + second;
printf("%d + %d = %d", first, second, sum);
}

26
Where Variables Are Declared? (cont.)
• Global Variables
• They are known throughout the program and may be used by any piece
of code.
• They will hold their value throughout the program's execution.
• They are created by declaring them outside of any function. Any
expression may access them, regardless of what block of code that
expression is in.
• They could be placed anywhere before its first use as long as it was not
in a function. However, it is usually best to declare global variables at
the top of the program.
• They take up memory the entire time your program is executing.

27
Example of Formal Parameters
int count;

void func1();
void func2();

int main() {
count = 100;
func1();
return 0;
}

void func1() {
int temp;
temp = count;
func2();
}

void func2() {
printf("%d\n", count);
}
28
C Scopes of Vision
• File scope
• Starts at the beginning of the file (also called a translation unit) and ends
with the end of the file. It refers only to those identifiers that are declared
outside of all functions. File scope identifiers are visible throughout the
entire file. Variables that have file scope are global.
• Block scope
• Begins with the opening { of a block and ends with its associated closing }.
However, block scope also extends to function parameters in a function
definition. That is, function parameters are included in a function's block
scope. Variables with block scope are local to their block.
• Function prototype scope
• Identifiers declared in a function prototype; visible within the prototype.
• Function scope
• Begins with the opening { of a function and ends with its closing }. Function
scope applies only to labels. A label is used as the target of a goto statement,
and that label must be within the same function as the goto.

29
const Type Qualifier
• Variables of type const may not be changed by your program.
(A const variable can be given an initial value, however.) The
compiler is free to place variables of this type into read-only
memory (ROM).
const int a = 10;

• It can be used to prevent the object pointed to by an argument


to a function from being modified by that function.
void func(const int *x) {
printf("%d\n", *x);
}

30
static Specifiers
• Permanent variables within their own function or file.
• They are not known outside their function or file, but they
maintain their values between calls.
• The static modifier has different effects upon local variables
and global variables.
• static Local Variables
• The compiler creates permanent storage for it, much as it creates
storage for a global variable.
• a static local variable is a local variable that retains its value between
function calls.
• static Global Variables
• A global variable known only to the file in which it is declared.

33
More on operators
• The Assignment Operator
𝑣𝑎𝑟_𝑛𝑎𝑚𝑒 = 𝑒𝑥𝑝𝑟𝑒𝑠𝑠𝑖𝑜𝑛;
• 𝑣𝑎𝑟 − 𝑛𝑎𝑚𝑒 is called 𝑙𝑣𝑎𝑙𝑢𝑒 while the 𝑒𝑥𝑝𝑟𝑒𝑠𝑠𝑖𝑜𝑛 is called 𝑟𝑣𝑎𝑙𝑢𝑒.
• 𝑙𝑣𝑎𝑙𝑢𝑒 should be modifiable.

• Multiple assignment
x = y = z = 0;

• Compound Assignments
x = x + 2; --> x += 2;

• Type Conversion in Assignments


• Expression are evaluated in the highest type.

35
The Increment and Decrement Operators
x = x + 1; --> ++x; or x++;
x = x - 1; --> --x; or x--;

• Prefix vs. Post fix increment/decrement

x = 10;
y = ++x; // x = 11 and y = 11

x = 10;
y = x++; // x = 11 and y = 10

36
Type Conversion in Expressions
IF an operand is a long double
THEN the second is converted to long double
ELSE IF an operand is a double
THEN the second is converted to double
ELSE IF an operand is a float
THEN the second is converted to float
ELSE IF an operand is an unsigned long
THEN the second is converted to unsigned long
ELSE IF an operand is long
THEN the second is converted to long
ELSE IF an operand is unsigned int
THEN the second is converted to unsigned int

37
Casting
• Explicit conversion of types
𝑡𝑦𝑝𝑒 𝑒𝑥𝑝𝑟𝑒𝑠𝑠𝑖𝑜𝑛

double x = 7.5;

int y = x; // Error
int y = (int)x; // ok

38
Control Statements
• Selection Statements
• The if-else statement
• The ?: alternative
• The switch statement
• Iteration Statements
• The for statement
• The while statement
• The do..while statement
• Jump Statements
• The return statement
• The goto statement
• The break statement
• The continue statement
• The exit() function

39
The if selection statements
if( condition ) {
...
statements;
...
}

if( condition )
single statement;

if( condition ) single statement;

40
The if-else selection statements
if( condition ) {
...
statements;
...
} else {
...
statements;
...
}

if( condition )
single statement;
else
single statement;

if( condition ) single statement;


else single statement;

41
Nested if-else selection statements
if( condition 1 ) { if( condition 1 )
... if( condition 2 )
if( condition 2 ) { statement;
...
statements; if( condition 1 )
... if( condition 2 )
} else { statement;
... else
statements; statement;
...
} if( condition 1 )
} else { if( condition 2 )
... statement;
if( condition 3 ) { else
... statement;
statements;
... if( condition 1 ) {
} else { if( condition 2 )
... statement;
statements; } else
... statement;
}
...
}
42
The if-else-if ladder
if (condition 1) int main()
statement 1; {
else int grade;
if (condition 2) printf("Please, enter your grade: ");
statement 2; scanf("%d", &grade);
...
else printf("Your rank is ");
if (condition N) if (grade >= 90)
statement N; printf("Excellent");
else else if (grade >= 80)
last statement; printf("Very good");
else if (grade >= 65)
if (condition 1) printf("Good");
statement 1; else if (grade >= 50)
else if (condition 2) printf("Passed");
else
statement 2;
printf("Fail");
... }
else if (condition N)
statement N;
else
last statement;

43
The ?: operator
int main()
{
int grade;
char * rank;

printf("Please, enter your grade: ");


scanf("%d", &grade);

if (grade >= 50)


printf("Passed\n");
else
printf("Failed\n");

grade >= 50 ? printf("Passed\n") : printf("Failed\n");


rank = grade >= 50 ? "Passed\n" : "Failed\n";
printf(rank);
printf(grade >= 50 ? "Passed\n" : "Failed\n");
}

44
The switch statement
switch (expression) {
case constant1:
code block 1;
break;
case constant2:
code block 2;
break;
case constant3:
code block 3;
break;
.
.
.
default:
code block N;
}

45
The switch statement (example 1)
int main()
{
char choice;

printf("Enter a digit (1-3): ");

choice = getchar();
switch (choice) {
case '1':
printf("One");
break;
case '2':
printf("Two");
break;
case '3':
printf("Three");
break;
default:
printf("Nothing correct");
}
}
46
The switch statement (example 2)
int main()
{
int choice;
printf("Enter a digit (1-9): ");
scanf("%d", &choice);
switch (choice) {
case 1:
case 2:
case 3:
case 4:
printf("it is between 1 and 4");
break;
case 5:
case 6:
printf("it is either 5 or 6");
break;
case 7:
case 8:
case 9:
printf("it is between 7 and 9");
break;
default:
printf("Nothing correct");
}
47
}
Nested switch statement (example 3)
int main()
{
int x, y;
printf("Enter two numbers: ");
scanf("%d%d", &x, &y);
switch (x) {
case 1:
switch (y) {
case 0:
printf("Division over zero");
break;
default:
printf("Y reciproque = %f", 1/(double)y);
break;
}
break;
default:
printf("%d * %d = %d", x, y, x*y);
}
}
48
The for statement
• Syntax
for(initialization; condition; iteration) {
// body
}

• At start, the initialization portion is executed,


• Next, condition is evaluated
• The loop body is executed if true,
• The loop finished if false.
• Next, the iteration portion is executed.
• The three portions are optional

49
The for statement (example 1)
int main() {
int x, n;
int sum = 0;

printf("Enter a value for n: ");


scanf("%d", &n);
for (x = 1; x <= n; x++) {
printf("%d\n", x);
sum += x;
}
printf("the sum from 1 to %d = %d\n", n, sum);
}

50
The for statement (example 2)
int main() {
int x, y;

for (x = 100, y = 200; x < y; x++, y--);


printf("The middle value is : %d", x);
}

int main() {
int x, y;

printf("Enter two integers for x & y (x < y): ");


scanf("%d%d", &x, &y);

for (; x < y; x++, y--);


printf("The middle value is : %d", x);
}

51
Nested for statement (example 3)
int main()
{
int i, j;

for (i = 0; i < 5; i++) {


for (j = 0; j < 4; j++) {
printf("%5d\t", (i + 1) * (j + 1));
}
printf("\n");
}

return 0;
} 1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16
5 10 15 20

52
The while statement
• Syntax
while(condition) {
// body of loop
}

• Condition is evaluated before executing the loop.

53
The while statement (example)
#include <stdio.h>
#include <conio.h>

int main() {
char ch = '\0';
while (ch != 's' && ch != 'S'){
ch = getch();
printf("%c\n", ch);
// Do something...
}

return 0;
}

54
The do-while statement
• Syntax
do {
// body of loop
} while (condition);

• Condition is evaluated after executing the loop.


• The body of the loop is executed at least once.

55
The do-while statement (example)
#include <stdio.h>
#include <conio.h>

int main() {
char stop;
do {
// Doing something...
printf("\nDo you want to stop? (Y/N) ");
stop = getche();
} while (stop !='y' && stop !='Y');

return 0;
}

56
for statement → while statement

for(initialization; condition; iteration) {


body;
}

initialization;
while(condition) {
body;
iteration;
}

57
for statement → do-while statement

for(initialization; condition; iteration) {


body;
}

initialization;
if(condition) {
do {
body;
iteration;
} while(condition);
}

58
The return statement
• Syntax
return [expression];

• To explicitly return from a method.


• It causes the execution to branch back to the caller of the
method.
• It immediately terminates the method in which it is executed.

59
The goto statement
• Syntax
goto label;
.
.
.
label:

• label is any valid label either before or after goto.

• MUST BE AVOIDED

60
The goto statement (example)
int main() {
int x = 1;
loop1:
printf("%d\n", x);
x++;
if (x <= 100)
goto loop1;
}

61
The break statement
• Syntax
break;

• Two usages
• To terminates a statement sequence in a switch statement.
• To exit a loop (stop the loop completely).

62
The break statement (example)
int main() {
int t;
for (t = 0; t < 100; t++) {
printf("%d ", t);
if(t == 10)
break;
}
return 0;
}

63
The continue statement
• Syntax
continue;

• To force an early iteration of a loop.


• In while and do-while loops, a continue statement causes
control to be transferred directly to the conditional expression
that controls the loop.
• In a for loop, control goes first to the iteration portion of the for
statement and then to the conditional expression.
• Any intermediate code is bypassed.

64
The continue statement (example)
int main() {
int i;
for (i = 0; i < 10; i++) {
printf("%d ", i);
if(i % 2 == 0)
continue; 01
printf("\n"); 23
} 45
return 0; 67
} 89

65
The exit() function
• Syntax
void exit(int return_code);

• The value of return_code is returned to the calling process,


which is usually the operating system.
• Zero is commonly used as a return code to indicate normal
program termination.
• Other arguments are used to indicate some sort of error.
• The header file stdlib.h should be included.

66
Functions
• Syntax ret_type function_name(parameter_list) {
body of the function
}
• ret-type specifies the type of data that the function returns. A function may
return any type of data except an array.
• parameter-list is a comma-separated list of variable names and their
associated types.
• The parameters receive the values of the arguments when the function
is called.
• An empty parameter list can be explicitly specified as such by placing
the keyword void inside the parentheses.
• all function parameters must be declared individually, each including
both the type and name. It takes this general form:

function_name(type varname1, type varname2, . . . , type varnameN)

67
Scope of a Function
• Each function is a discrete block of code. Thus, a function
defines a block scope.
• Function's code is private to that function and cannot be
accessed by any statement in any other function except
through a call to that function.
• The code that constitutes the body of a function is hidden from
the rest of the program, and unless it uses global variables, it
can neither affect nor be affected by other parts of the program.
• Variables that are defined within a function are local variables.
• They are created when the function is entered and are destroyed upon
exit.
• They cannot hold their values between function calls.
• Argument variables are local variables.

68
Functions (example 1)
int min(int a, int b) {
if (a < b)
return a;
else
return b;
}

int max(int a, int b) {


return a > b? a : b;
x = 12 & y = 17
}
The lower number is : 12
The higher number is : 17
int main() {
17 >= 12
int x = 12, y = 17;
int minimum = min(x, y), maximum = max(x, y);
printf("x = %d & y = %d\n", x, y);
printf("The lower number is : %d\n", minimum);
printf("The higher number is : %d\n", maximum);
printf("%d >= %d\n", max(x, y), min(x, y));
}

69
Functions (example 2)
#define PI 3.14159265358979323846

int fact(int n) {
int result, i;
for (i = result = 1; i <=n; i++)
result *= i;
return result;
}
5! = 120
int main() {
sin(30.000000) = 0.500183
int n = 5;
sin(30.000000) = 0.500000
double x = 30;
sin(30.000000) = 0.500000
double pi = 3.14159265358979323846;
sin(30.000000) = 0.500000
printf("%d! = %d\n", n, fact(n));
printf("sin(%f) = %f\n", x, sin(x*22/7/180));
printf("sin(%f) = %f\n", x, sin(x*355/113/180));
printf("sin(%f) = %f\n", x, sin(x*pi/180));
printf("sin(%f) = %f\n", x, sin(x*PI/180));
}
70
Call-by-value vs Call-by-reference
• Call-by-value
• Copies the value of an argument into the formal parameter of the
subroutine.
• Changes made to the parameter have no effect on the argument outside
the function.
• Call-by-reference
• The address of an argument is copied into the parameter.
• The address is used to access the actual argument used in the call.
• Changes made to the actual parameter through the address affect the
argument outside the function.
C supports call-by-value only

71
Call-by-value vs Call-by-reference (example 1)
void swap(int a, int b) {
int temp = a;
printf("Begin swap() : a = %d & b = %d\n", a , b);
a = b;
b = temp;
printf("End swap() : a = %d & b = %d\n", a , b);
}

int main() {
int x = 5, y = 7;

printf("Before calling swap() : x = %d & y = %d\n", x , y);


swap(x, y);
printf("After calling swap() : x = %d & y = %d\n", x , y);
return 0;
}

72
Call-by-value vs Call-by-reference (example 2)
void swap(int * a, int * b) {
int temp = *a;
printf("Begin swap() : a = %d & b = %d\n", *a , *b);
*a = *b;
*b = temp;
printf("End swap() : a = %d & b = %d\n", *a , *b);
}

int main() {
int x = 5, y = 7;

printf("Before calling swap() : x = %d & y = %d\n", x , y);


swap(&x, &y);
printf("After calling swap() : x = %d & y = %d\n", x , y);
return 0;
}

C supports call-by-value only

73
Returning from a Function
• A function terminates execution and returns to the caller in
two ways:
• The first occurs when the last statement in the function has executed,
and, conceptually, the function's ending curly brace (}) is encountered.
• Most functions rely on the return statement to stop execution either
because a value must be returned or to make a function's code simpler
and more efficient.
• The return Statement has two important uses:
• It causes an immediate exit from the function. That is, it causes program
execution to return to the calling code.
• It can be used to return a value.

74
Returning Values
• All functions, except those of type void, return a value specified by the
return statement.
• In C89, if a non-void function executes a return statement that does not include
a value, then a garbage value is returned (bad practice).
• In C99 (and C++), a non-void function must use a return statement that
returns a value.
• If a function is specified as returning a value, any return statement within it must
have a value associated with it.
• However, if execution reaches the end of a non-void function (that is, encounters the
function's closing curly brace), a garbage value is returned.

• As long as a function is not declared as void, you can use it as an operand in


an expression.
x = power(y);
if (max(x, y) > 100) printf("greater");
for (ch = getchar(); isdigit(ch);) ...;

75
Types of functions
• Computational
• These functions are specifically designed to perform operations on their
arguments and return a value based on that operation.
• A computational function is a ''pure" function.
• Examples: sqrt() and sin().
• Manipulator
• They manipulates information and returns a value that simply indicates
the success or failure of that manipulation.
• Examples: fclose() (0 if successful, EOF if not).
• Procedure
• They have no explicit return value. The function is strictly procedural
and produces no value.
• Examples: exit().

76
Recursion
• A function can call itself. In this case, the function is said to be
recursive.
• Recursion is the process of defining something in terms of
itself, and is sometimes called circular definition.
• Requirements:
• Recursive formula
• Stop condition
• Testing the stop condition before the recursive call

77
Recursion (example 1)
/* non-recursive */
int factorial(int n) {
int i, answer;
answer = 1;
for (i = 1; i <= n; i++)
answer = answer * i;
return answer;
}

int main() {
int n = 5;

printf("(%d)! = %d", n, factorial(n));


return 0;
}

78
Recursion (example 2)
/* recursive */
int factorial(int n) {
int answer;
if (n == 1)
return 1;
answer = factorial(n - 1) * n; /* recursive call */
return answer;
}

int main() {
int n = 5;

printf("(%d)! = %d", n, factorial(n));


return 0;
}

79
Function Prototypes
• In modern, properly written C programs, all functions must be declared
before they are used.
• Function prototypes were not part of the original C language, but were
added by C89. However, prototypes are required by C++.
• Prototypes enable the compiler to provide stronger type checking.
• The compiler will also catch differences between the number of arguments
used to call a function and the number of parameters in the function.
type func_name(type parm_namel, type parm_name2, ..., type parm_nameN);

• The use of parameter names is optional. However, they enable the compiler
to identify any type mismatches by name when an error occurs, so it is a
good idea to include them.

80
Function Prototypes (example)
void f(int a, int b); void f(int a, int b) {
void f(int, int); printf("%d ", a % b);
}

int main() { int main() {


f(10, 3); f(10, 3);
return 0; return 0;
} }

void f(int a, int b) {


printf("%d ", a % b);
}

81
Bizarre! (1)
#include <stdio.h>

int main() {
int n;

n = 5; n++, n, n : 5, 6, 6
printf("n++, n, n : %d, %d, %d\n", n++, n, n); n:6
printf("n : %d\n\n", n);
n, n++, n : 6, 5, 6
n = 5;
n:6
printf("n, n++, n : %d, %d, %d\n", n, n++, n);
printf("n : %d\n\n", n);
n, n, n++ : 6, 6, 5
n = 5; n:6
printf("n, n, n++ : %d, %d, %d\n", n, n, n++);
printf("n : %d\n\n", n);

return 0;
}

84
Bizarre! (2)
#include <stdio.h>

int main() {
int n;

n = 5; ++n, n, n : 6, 6, 6
printf("++n, n, n : %d, %d, %d\n", ++n, n, n); n:6
printf("n : %d\n\n", n);
n, ++n, n : 6, 6, 6
n = 5;
n:6
printf("n, ++n, n : %d, %d, %d\n", n, ++n, n);
printf("n : %d\n\n", n);
n, n, ++n : 6, 6, 6
n = 5; n:6
printf("n, n, ++n : %d, %d, %d\n", n, n, ++n);
printf("n : %d\n\n", n);

return 0;
}

85
Bizarre! (3)
#include <stdio.h>

int main() {
int n;

n = 5; n++, n++, n++ : 7, 6, 5


printf("n++, n++, n++ : %d, %d, %d\n", n++, n++, n++); n:8
printf("n : %d\n\n", n);
n++, n, n++ : 6, 7, 5
n = 5;
printf("n++, n, n++ : %d, %d, %d\n", n++, n, n++);
n:7
printf("n : %d\n\n", n);
++n, ++n, ++n: 8, 8, 8
n = 5; n:8
printf("++n, ++n, ++n: %d, %d, %d\n", ++n, ++n, ++n);
printf("n : %d\n\n", n);

return 0;
}

86
Bizarre! (4)
#include <stdio.h>

int main() {
int n;

n = 5; ++n, n, ++n: 7, 7, 7
printf("++n, n, ++n: %d, %d, %d\n", ++n, n, ++n); n:7
printf("n : %d\n\n", n);
n++, n, ++n : 6, 7, 7
n = 5;
printf("n++, n, ++n : %d, %d, %d\n", n++, n, ++n);
n:7
printf("n : %d\n\n", n);
n, ++n, n++ : 7, 7, 5
n = 5; n:7
printf("n, ++n, n++ : %d, %d, %d\n", n, ++n, n++);
printf("n : %d\n\n", n);

return 0;
}

87
Bizarre! (5)
#include <stdio.h>

int main() {
int n;

n = 5; n++, ++n, n : 6, 7, 7
printf("n++, ++n, n : %d, %d, %d\n", n++, ++n, n); n:7
printf("n : %d\n\n", n);
++n, n, n++ : 7, 7, 5
n = 5;
printf("++n, n, n++ : %d, %d, %d\n", ++n, n, n++); n:7
printf("n : %d\n\n", n);
++n, n++, n : 7, 5, 7
n = 5; n:7
printf("++n, n++, n : %d, %d, %d\n", ++n, n++, n);
printf("n : %d\n\n", n);

return 0;
}

88
Arrays
• An array is a collection of variables of the same type that are
referred to through a common name.
• A specific element in an array is accessed by an index.
• In C, all arrays consist of contiguous memory locations.
• The lowest address corresponds to the first element and the highest
address to the last element.
• The most common array is the string, which is simply an array
of characters terminated by a null.

89
Single-Dimension Array
• Syntax: type var_name[size];
double balance[100];

• In C89, The size of an array must be specified using a constant


expression.
• C99 allows arrays whose sizes are determined at run time.
• An element is accessed by placing the index of the element
within square brackets after the name of the array.
balance[3] = 12.23;

• In C, all arrays have 0 as the index of their first element.


char p[10];

90
Single-Dimension Array (example)
int main(void) {
int x[10]; /* this declares a 10-integer array */
int t;
/* load x with values 0 through 9 */
for (t = 0; t < 10; ++t)
x[t] = t;
/* display contents of x */
for (t = 0; t < 10; ++t)
printf("%d ", x[t]);

printf("\nThe size of the element x[0] is %d bytes", sizeof(x[0]));


printf("\nThe size of the array x is %d bytes", sizeof(x));
return 0;
} 0123456789
The size of the element x[0] is 4 bytes
The size of the array x is 40 bytes

total bytes = sizeof(base type) × length of array

91
Array storage and Bound checking
• As a programmer, it is your job to provide bounds checking
where needed.
• The following code will compile without error (bug):
int count[10], i;
/* this causes count to be overrun */
for(i=0; i<100; i++) count[i] = i;

• Single-dimension arrays are essentially lists that are stored in


contiguous memory locations in index order.
char a[7];

92
Generating a Pointer to an Array
• The name of the array is a pointer to the first element:
int *p;
int sample[10];
p = sample;

• You may also use the address of the first element:


int *p;
int sample[10];
p = &sample[0];

93
Passing Single-Dimension Arrays to Functions
• In C, you cannot pass an entire array as an argument to a
function.
• You can, however, pass a pointer to an array by specifying the array's
name without an index.
void func1(int *x) { /* pointer */
/* . . . */
}
void func1(int x[10]) { /* sized array */
/* . . . */
}
void func1(int x[]) { /* unsized array */
/* . . . */
}

int main(void) {
int i[10];
func1(i);
/* . . . */
}
94
Strings
• In C, a string is a null-terminated character array. (A null is
zero.)
• Thus, a string contains the characters that make up the string followed
by a null.
• The null-terminated string is the only type of string defined by C.
• When declaring a character array that will hold a string, you
need to declare it to be one character longer than the largest
string that it will hold.
• Example: declare an array str that can hold a 10-character string:
char str[11];

95
Some common string functions
• Include the header <string.h>
Name Function
strcpy(s1, s2) Copies s2 into s1
strcat(s1, s2) Concatenates s2 onto the end of s1
strlen(s1) Returns the length of s1
strcmp(s1, s2) Returns 0 if s1 and s2 are the same; less than 0 if
s1<s2; greater than 0 if s1>s2
strchr(s1, ch) Returns a pointer to the first occurrence of ch in s1
strstr(s1, s2) Returns a pointer to the first occurrence of s2 in s1

96
Strings (example)
#include <stdio.h>
#include <string.h>
int main(void) {
char s1[80], s2[80];
gets(s1);
gets(s2);
printf("lengths: %d %d\n", strlen(s1), strlen(s2));
if (!strcmp(s1, s2))
printf("The strings are equal\n");
strcat(s1, s2);
printf("%s\n", s1); hello
strcpy(s1, "This is a test.\n");
hello
printf(s1);
if (strchr("hello", 'e')) lengths: 5 5
printf("e is in hello\n"); The strings are equal
if (strstr("hi there", "hi")) hellohello
printf("found hi"); This is a test.
return 0; e is in hello
} found hi

97
Two-Dimensional Arrays
• A two-dimensional array is, essentially, an array of one-
dimensional arrays.
#include <stdio.h> 1 2 3 4
int main(void) { 5 6 7 8
int num[3][4]; 9 10 11 12
int t, i;
for (t = 0; t < 3; ++t)
for (i = 0; i < 4; ++i)
num[t][i] = (t * 4) + i + 1;
/* now print them out */
for (t = 0; t < 3; ++t) {
for (i = 0; i < 4; ++i)
printf("%3d ", num[t][i]);
printf("\n");
}
return 0;
}
98
Arrays of Strings
• To create an array of strings, use a two-dimensional character
array:
char str_array[30][80];

• To access an individual string, you simply specify only the left


index:
gets(str_array[2]);

or
gets(&str_array[2][0]);

99
Multidimensional Arrays
• To declare N dimension array:
type name[Size1][Size2][Size3] . . .[SizeN];

• When passing multidimensional arrays into functions, you


must declare all but the leftmost dimension.
int m[4][3][6][5];

void func1(int d[][3][6][5]) {


/* . . . */
}

100
Indexing Pointers
• An array name without an index is a pointer to the first
element in the array.
char p[10];
p == &p[0];

• Conversely, a pointer can be indexed as if it were declared to be


an array.
int *p, i[10];
p = i;
/* assign using index */
p[5] = 100;
/* assign using pointer arithmetic */
*(p+5) = 100;
*(i+5) = 100;

101
Indexing Pointers (cont.)
#define HEIGHT 3 printf("\n");
#define WIDTH 4 for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
int main(void) { printf("%d\t", *((int *)a + i * WIDTH + j));
int i, j; }
int a[HEIGHT][WIDTH]; printf("\n");
int *p = (int *)a; }

for (i = 0; i < HEIGHT; i++) for (i = 0; i < HEIGHT * WIDTH; i++) {


for (j = 0; j < WIDTH; j++) if (i % WIDTH == 0)
a[i][j] = (i + 1)*(j + 1); printf("\n");
printf("%d\t", *(p + i));
for (i = 0; i < HEIGHT; i++) { }
for (j = 0; j < WIDTH; j++)
printf("%d\t", a[i][j]); return 0;
printf("\n"); }
}

1 2 3 4
2 4 6 8
3 6 9 12

102
#include <stdio.h>

int main() {
int array[3] = {1, 2, 3};
printf("L00: array[0]=%d\n", array[0]); L00: array[0]=1
printf("L01: array[1]=%d\n", array[1]); L01: array[1]=2
printf("L02: array[2]=%d\n", array[2]); L02: array[2]=3
printf("L03: &array[0]=%x\n", &array[0]); L03: &array[0]=b29ffc34
printf("L04: &array[1]=%x\n", &array[1]); L04: &array[1]=b29ffc38
printf("L05: &array[2]=%x\n", &array[2]); L05: &array[2]=b29ffc3c
printf("L06: array=%x\n", array); L06: array=b29ffc34
printf("L07: &array=%x\n", &array); L07: &array=b29ffc34
printf("L08: sizeof(array)=%d\n", sizeof(array)); L08: sizeof(array)=12
return 0;
}

103
#include <stdio.h>

int main() {
char *array[3] = {"First", "Second", "Third"};
printf("L00: array[0]=%s\n", array[0]); L00: array[0]=First
printf("L01: array[1]=%s\n", array[1]); L01: array[1]=Second
printf("L02: array[2]=%s\n", array[2]); L02: array[2]=Third
printf("L03: &array[0]=%x\n", &array[0]); L03: &array[0]=b57ffcd0
printf("L04: &array[1]=%x\n", &array[1]); L04: &array[1]=b57ffcd8
printf("L05: &array[2]=%x\n", &array[2]); L05: &array[2]=b57ffce0
printf("L06: array=%x\n", array); L06: array=b57ffcd0
printf("L07: &array=%x\n", &array); L07: &array=b57ffcd0
printf("L08: sizeof(array)=%d\n", sizeof(array)); L08: sizeof(array)=24
return 0;
}

104
#include <stdio.h>

int main() {
char array[3][10] = {"1st", "2nd", "3rd"};
printf("L00: array[0]=%s\n", array[0]); L00: array[0]=1st
printf("L01: array[1]=%s\n", array[1]); L01: array[1]=2nd
printf("L02: array[2]=%s\n", array[2]); L02: array[2]=3rd
printf("L03: &array[0]=%x\n", &array[0]); L03: &array[0]=3d7ffd40
printf("L04: &array[1]=%x\n", &array[1]); L04: &array[1]=3d7ffd4a
printf("L05: &array[2]=%x\n", &array[2]); L05: &array[2]=3d7ffd54
printf("L06: array=%x\n", array); L06: array=3d7ffd40
printf("L07: &array=%x\n", &array); L07: &array=3d7ffd40
printf("L08: sizeof(array)=%d \n", sizeof(array)); L08: sizeof(array)=30
return 0;
}

105
Arrays initialization
• Syntax:
char array_name[size] = "string";
char str[9] = "I like C";

char str[9] = {'I', ' ', 'l', 'i', 'k', 'e',' ', 'C', '\0’};

int sqrs[4][2] ={
{ 1, 1 },
{ 2, 4 },
{ 3, 9 },
{ 4, 16 }
};

106
Unsized Array Initializations
char e1[12] = "Read error\n";
char e2[13] = "Write error\n";
char e3[18] = "Cannot open file\n";
• If, in an array initialization statement, the size of the array is
not specified, the compiler automatically creates an array big
enough to hold all the initializers present.
char e1[] = "Read error\n";
char e2[] = "Write error\n";
char e3[] = "Cannot open file\n";
int sqrs[][2] ={
{ 1, 1 },
{ 2, 4 },
{ 3, 9 },
{ 4, 16 }
};

107
Variable-Length Arrays (C99)
• In C99, you can declare an array whose dimensions are
specified by any valid expression, including those whose value
is known only at run time.
• Only local arrays (that is, those with block scope or prototype scope)
can be of variable length.
void f(int dim) {
char str[dim]; /* a variable-length character array */
/* . . . */
}

108
Pointers
• YOU MUST UNDERSTAND POINTERS because:
1. pointers provide the means by which functions
can modify their calling arguments.
2. pointers support dynamic allocation.
3. pointers can improve the efficiency of certain
routines.
4. pointers provide support for dynamic data
structures, such as binary trees and linked lists.
• A pointer is a variable that holds a memory
address. This address is the location of
another object (typically another variable) in
memory.

109
Pointer Variables
• Syntax:
type *name;

• The base type of the pointer defines the type of object to which
the pointer will point.
• Technically, any type of pointer can point anywhere in memory.
• However, all pointer operations are done relative to the
pointer's base type.

110
The Pointer Operators
• Two pointer operators:
• The & operator:
• A unary operator that returns the memory address of its operand.
m = &count;

• The * operator:
• A unary operator that returns the value located at the address that
follows.
q = *m;

111
Pointer Expressions
• Pointer Assignments
#include <stdio.h>
int main() {
int x = 99;
int *p1, *p2;
p1 = &x;
p2 = p1;
/* print the value of x twice */
printf("Values at p1 and p2: %d %d\n", *p1, *p2);
/* print the address of x twice */
printf("Addresses pointed to by p1 and p2: %p %p", p1, p2);
return 0;
}
Values at p1 and p2: 99 99
Addresses pointed to by p1 and p2: 000000000061FE0C 000000000061FE0C

112
Generic pointer
• In C, it is permissible to assign a void * pointer (generic
pointer) to any other type of pointer.
• It is also permissible to assign any other type of pointer to a
void * pointer.
• The void * type allows a function to specify a parameter that is
capable of receiving any type of pointer argument without
reporting a type mismatch.
• Used to refer to raw memory (such as that returned by the
malloc() function)

113
Pointer Conversions
• Except for void *, all other pointer conversions must be
performed by using an explicit cast. (C++ includes void *)
• Conversion of one type of pointer into another type may create
undefined behavior.
#include <stdio.h>
int main() {
double x = 100.1, y;
int *p;
/* The next statement causes p (which is an
integer pointer) to point to a double. */
p = (int *) &x;
/* The next statement does not operate as expected. */
y = *p; /* attempt to assign y the value x through p */
/* The following statement won't output 100.1. */
printf("\nThe (incorrect) value of x is: %f", y);
return 0;
}
The (incorrect) value of x is: 1717986918.000000
114
Pointer Operations
• Two arithmetic operations:
• Addition
• Subtraction
• Pointer Comparisons
• According to the location in the memory

115
Pointers and Arrays
char str[80], *p1;
p1 = str;

str[4] == *(p1+4);
• Arrays of Pointers:
int var;
int *x[10];
x[2] = &var;

void display_array(int *q[]) {


int t;
for (t=0; t<10; t++)
printf("%d ", *q[t]);
}

116
Multiple Indirection
• A pointer point to another pointer that points to the target
value.
#include <stdio.h>
int main() {
int x, *p, **q;
x = 10;
p = &x;
q = &p;
/* print the value of x */
printf("%d", **q);
return 0;
}

117
Initializing Pointers
char *p = 0;
char *p = NULL;
#include <stdio.h>
#include <string.h>
int search(char *p[], char *name);
/* null pointer constant ends the list */
char *names[] ={ "Herb", "Rex", "Dennis", "John", NULL };

int main() {
if (search(names, "Dennis") != -1)
printf("Dennis is in list.\n");
if (search(names, "Bill") == -1)
printf("Bill not found.\n");
return 0;
}

/* Look up a name. */
int search(char *p[], char *name) {
register int t;
for (t=0; p[t]; ++t)
if (!strcmp(p[t], name)) return t;
return -1; /* not found */
}
118
Pointers to Functions
#include <stdio.h>
#include <string.h>
void check(char *a, char *b, int (*cmp)(const char *, const char *));

int main() {
char s1[80], s2[80];
int (*p)(const char *, const char *); /* function pointer */
p = strcmp; /* assign address of strcmp to p */
printf("Enter two strings.\n");
gets(s1);
gets(s2);
check(s1, s2, p); /* pass address of strcmp via p */
return 0;
}

void check(char *a, char *b, int (*cmp)(const char *, const char *)) {
printf("Testing for equality.\n");
if ((*cmp)(a, b) == 0)
printf("Equal");
else
printf("Not Equal");
119
}
Pointers to Functions (cont.)
#include <stdio.h> void check(char *a, char *b,
#include <ctype.h> int (*cmp)(const char *, const char *)) {
#include <stdlib.h> printf("Testing for equality.\n");
#include <string.h> if ((*cmp)(a, b) == 0)
void check(char *a, char *b, printf("Equal");
int (*cmp)(const char *, const char *)); else
int compvalues(const char *a, const char *b); printf("Not Equal");
int main(void) { }
char s1[80], s2[80];
printf("Enter two values or two strings.\n"); int compvalues(const char *a, const char *b) {
gets(s1); if (atoi(a) == atoi(b))
gets(s2); return 0;
if (isdigit(*sl)) { else
printf("Testing values for equality.\n"); return 1;
check(s1, s2, compvalues); }
}
else {
printf("Testing strings for equality.\n");
check(s1, s2, strcmp);
}
return 0;
}

120
Dynamic Memory Allocation
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main() {
char * s;
int i;

s = (char *) malloc(80);
if (!s) {
printf("Memory request failed.\n");
exit(1);
}
gets(s);
for(i = strlen(s) - 1; i >= 0; i--)
putchar(s[i]);
free(s); /* release memory*/
return 0;
}

121
Dynamic Memory Allocation (cont.)
#include <stdio.h> int pwr(int a, int b) {
#include <stdlib.h> int t = 1;
int pwr(int a, int b); for (; b; b--)
int main() { t = t * a;
int(*p)[10]; return t;
int i, j; }
/* allocate memory to hold a 4 x 10 array */
p = malloc(40 * sizeof(int));
if (!p) { 1 1 1 1
printf("Memory request failed.\n"); 2 4 8 16
exit(1); 3 9 27 81
} 4 16 64 256
for (i = 0; i < 4; i++) 5 25 125 625
for (j = 0; j < 10; j++)
6 36 216 1296
p[i][j] = pwr(j + 1, i + 1);
for (j = 0; j < 10; j++) { 7 49 343 2401
for (i = 0; i < 4; i++) 8 64 512 4096
printf("%8d", p[i][j]); 9 81 729 6561
printf("\n"); 10 100 1000 10000
}
free(p); /* release memory*/
return 0;
}

122
Dynamic Memory Allocation (notes.)
• Alternative:
malloc(n * sizeof(int)) <==> calloc(n, sizeof(int));
• calloc() set the allocated memory to zero
• It is slower than malloc()
• Result casting (for C++ compatibility):
p = (int (*)[10]) malloc(40 * sizeof(int));

123
Constant pointer vs Pointer to constant

int a = 10; int a = 10;


const int *ptr = &a; int *const ptr = &a;
*ptr = 5; // wrong *ptr = 5; // right
ptr++; // right ptr++; // wrong

const int *const ptr = &a;

124
Structures, Unions, Enumerations, and typedef
• The C language gives you five ways to create a custom data
type:
• The structure: a grouping of variables under one name and is called an
aggregate data type.
• The union: enables the same piece of memory to be defined as two or
more different types of variables.
• The bit-field: a special type of structure or union element that allows
easy access to individual bits.
• The enumeration: a list of named integer constants.
• The typedef keyword: defines a new name for an existing type.

125
Structures
• A collection of variables referenced under one name, providing
a convenient means of keeping related information together.
• A structure declaration forms a template that can be used to
create structure objects (i.e. instances of a structure).
• The variables that make up the structure are called members
(elements or fields also).

126
Declaring structures and their variables
• Syntax:
struct tag { struct tag {
type member-name; type member-name;
type member-name; type member-name;
type member-name; type member-name;
. .
. .
. .
}; } structure-variables;

• Declaring variables of type structure:


struct {
type member-name;
struct tag var_name; type member-name;
type member-name;
.
.
.
} structure-variables;

127
Structures (example)
struct addr {
char name[30];
char street[40];
char city[20];
char state[3];
unsigned long int zip;
};
struct addr addr_info;
struct addr { struct {
char name[30]; char name[30];
char street[40]; char street[40];
char city[20]; char city[20];
char state[3]; char state[3];
unsigned long int zip; unsigned long int zip;
} addr_info; } addr_info;

128
Accessing Structure Members
• Syntax: object_name.member_name

addr_info.zip = 12345;

printf("%lu", addr_info.zip);

gets(addr_info.name);

for(t=0; addr_info.name[t]; ++t)


putchar(addr_info.name[t]);

129
Structure Assignments
#include <stdio.h>

int main() {
struct {
int a;
int b;
} x, y;
x.a = 10;
y = x; /* assign one structure to another */
printf("%d", y.a);
return 0;
}

130
Arrays of Structures
struct addr addr_list[100];

printf("%lu", addr_list[2].zip);

addr_list[2].name[0] = 'X';

131
A Mailing List Example
#include <stdio.h> int main(void) {
#include <stdlib.h> char choice;
/* initialize the structure array */
#define MAX 100 init_list();
for (;;) {
struct addr { choice = menu_select();
char name[30]; switch (choice) {
char street[40]; case 1:
char city[20]; enter();
char state[3]; break;
unsigned long int zip; case 2:
} addr_list[MAX]; delete ();
break;
void init_list(void), enter(void); case 3:
void delete (void), list(void); list();
int menu_select(void), find_free(void); break;
case 4:
exit(0);
}
}
return 0;
}

132
A Mailing List Example (cont.)
/* Initialize the list. */ /* Input addresses into the list. */
void init_list(void) { void enter(void) {
register int t; int slot;
for (t = 0; t < MAX; ++t) char s[80];
addr_list[t].name[0] = '\0'; slot = find_free();
} if (s1ot == -1) {
printf("\nList Full");
/* Get a menu selection. */ return;
int menu_select(void) { }
char s[80]; printf("Enter name: ");
int c; gets(addr_list[slot].name);
printf("1. Enter a name\n"); printf("Enter street: ");
printf("2. Delete a name\n"); gets(addr_list[slot].street);
printf("3. List the file\n"); printf("Enter city: ");
printf("4. Quit\n"); gets(addr_list[slot].city);
do { printf("Enter state: ");
printf("\nEnter your choice: "); gets(addr_list[slot].state);
gets(s); printf("Enter zip: ");
c = atoi(s); gets(s);
} while (c < 1 || c > 4); addr_list[slot].zip = strtoul(s, '\0', 10);
return c; }
}

133
A Mailing List Example (cont.)
/* Display the list on the screen. */
void list(void) {
register int t;
/* Find an unused structure. */
for (t = 0; t < MAX; ++t) {
int find_free(void) {
if (addr_list[t].name[0]) {
register int t;
printf("%s\n", addr_list[t].name);
for (t = 0; addr_list[t].name[0] && t < MAX; ++t)
printf("%s\n", addr_list[t].street);
;
printf("%s\n", addr_list[t].city);
if (t == MAX)
printf("%s\n", addr_list[t].state);
return -1; /* no slots free */
printf("%lu\n\n", addr_list[t].zip);
return t;
}
}
}
printf("\n\n");
/* Delete an address. */
}
void delete (void) {
register int slot;
char s[80];
printf("enter record #: ");
gets(s);
slot = atoi(s);
if (s1ot >= 0 && slot < MAX)
addr_list[slot].name[0] = '\0';
}

134
Passing Structures to Functions
struct fred {
char x;
int y;
float z;
char s[10];
} mike;

• Passing Structure Members to Functions


func(mike.x); /* passes character value of x */
func2(mike.y); /* passes integer value of y */
func3(mike.z); /* passes float value of z */
func4(mike.s); /* passes address of string s */
func(mike.s[2]); /* passes character value of s[2] */

• Passing Structure Members Pointers to Functions


func(&mike.x); /* passes address of character x */
func2(&mike.y); /* passes address of integer y */
func3(&mike.z); /* passes address of float z */
func4(mike.s); /* passes address of string s */
func(&mike.s[2]); /* passes address of character s[2] */

135
Passing Structures to Functions
• Passing Entire Structures to Functions
/* Define a structure type. */ struct struct_type {
struct struct_type { int a, b;
int a, b; char ch;
char ch; };
};
struct struct_type2 {
void f1(struct struct_type parm); int a, b;
char ch;
int main(void) { };
struct struct_type arg;
arg.a = 1000; void f1(struct struct_type2 parm);
f1(arg);
return 0; int main(void) {
} struct struct_type arg;
arg.a = 1000;
void f1(struct struct_type parm) { f1(arg); /* type mismatch */
printf("%d", parm.a); return 0;
} }

void f1(struct struct_type2 parm) {


printf("%d", parm.a);
}
136
Structure Pointers
struct bal {
float balance;
char name[80];
} person;

int main() {
/* declare a structure pointer */
struct bal *p;
p = &person;

(*p).balance = 123.45;
p–> balance = 123.45;
return 0;
}

137
Nested Structures
struct emp {
/* nested structure */
struct addr address;
float wage;
} worker;

worker.address.zip = 93456;

138
Unions
• Syntax: union tag {
type member_name;
type member_name;
type member_name;
.
.
.
} union_variables;

union u_type {
short i;
char ch;
};
union u_type cnvt;

139
Unions (example)
#include <stdio.h>
#include <stdlib.h>
union pw {
short int i;
char ch[2];
};
int putw(short int num, FILE *fp);
int main(void) {
FILE *fp;
fp = fopen("test.tmp", "wb+");
if (fp == NULL) {
printf("Cannot open file.\n");
exit(1);
}
putw(1025, fp); /* write the value 1025 */
fclose(fp);
return 0;
}
int putw(short int num, FILE *fp) {
union pw word;
word.i = num;
putc(word.ch[0], fp); /* write first half */
return putc(word.ch[1], fp); /* write second half */
}
140
Bit-Fields
• Allows you to access a single bit.
• If storage is limited, you can store several Boolean (true/false) variables
in one byte.
• Certain devices transmit status information encoded into one or more
bits within a byte.
• Certain encryption routines need to access the bits within a byte.

141
Bit-Fields
(status port of a serial communications adapter)
struct status_type { Bit Meaning When Set
unsigned delta_cts : 1; 0 Change in clear-to-send line
unsigned delta_dsr : 1;
unsigned tr_edge : 1; 1 Change in data-set-ready
unsigned delta_rec : 1; 2 Trailing edge detected
unsigned cts : 1; 3 Change in receive line
unsigned dsr : 1;
unsigned ring : 1; 4 Clear-to-send
unsigned rec_line : 1; 5 Data-set-ready
} status;
6 Telephone ringing
status = get_port_status();
7 Received signal
if (status.cts)
printf("clear to send");
if (status.dsr)
printf("data ready");
status.ring = 0;

142
Bit-Fields (bypassing & mixing)
struct status_type { • Restrictions:
unsigned : 4;
unsigned cts : 1; • You cannot take the address of
unsigned dsr : 1; a bit-field.
} status; • Bit-fields cannot be arrayed.
struct emp { • You cannot know, from
struct addr address; machine to machine, whether
float pay; the fields will run from right to
/* lay off or active */
left or from left to right;
unsigned lay_off : 1;
/* hourly pay or wage */
unsigned hourly : 1;
/* IRS deductions */
unsigned deductions : 3;
};

143
Enumerations
• A set of named integer constants.
• Syntax: switch (money) {
case penny:
enum tag { enumeration list } variable_list; printf("penny");
break;
case nickel:
enum coin { penny, nickel, dime, quarter,
printf("nickel");
half_dollar, dollar};
break;
case dime:
enum coin money; printf("dime");
break;
case quarter:
if (money == quarter) printf("quarter");
printf("Money is a quarter.\n"); break;
case half_dollar:
printf("half_dollar");
printf("%d %d", penny, dime); break;
case dollar:
printf("dollar");
}

144
Enumeration (cont.)
enum coin { penny, nickel, dime, quarter, half_dollar, dollar };

char name[][12] = {
"penny",
"nickel",
"dime",
"quarter",
"half_dollar",
"dollar“
};

printf("%s", name[money]);

• Initializing enumeration constants:


enum coin { penny, nickel, dime, quarter=100, half_dollar, dollar };

145
An Important Difference between C and C++
struct MyStruct {
int a;
int b;
};

• C variable declaration:
struct MyStruct obj;

• C++ variable declaration:


MyStruct obj;

• This applies to structures, unions, and enumerations.

146
Using sizeof()
struct s { union u {
char ch; char ch;
int i; int i;
double f; double f;
}; 1 }; 1
int main() { 4 int main() { 4
char ch; 8 char ch; 8
int i; 16 int i; 8
double f; double f;
struct s s_var; union u u_var;
printf("%d\n", sizeof(ch)); printf("%d\n", sizeof(ch));
printf("%d\n", sizeof(i)); printf("%d\n", sizeof(i));
printf("%d\n", sizeof(f)); printf("%d\n", sizeof(f));
printf("%d\n", sizeof(s_var)); printf("%d\n", sizeof(u_var));

return 0; return 0;
} }

147
typedef
• Define new data type names.
• Syntax: typedef type newname;
typedef float balance;
balance over_due;
typedef balance overdraft;
#define BALANCE float
struct s {
char ch;
int i;
double f;
};
typedef struct s sStruct;

148
Preprocessor directives
#define #undef #ifdef #ifndef

#if #elif #else #endif

#include #line #pragma #error

• All preprocessor directives begin with a # sign.


• Each preprocessing directive must be on its own line.

149
#define
• Syntax:
#define macro-name char-sequence
#define LEFT 1
#define RIGHT 0
printf("%d %d %d", RIGHT, LEFT, LEFT + 1);
#define ONE 1
#define TWO ONE+ONE
#define THREE ONE+TWO
#define E_MS "standard error on input\n"
/* . . . */
printf(E_MS);
#define LONG_STRING "this is a very long \
string that is used as an example"

150
Defining Function-like Macros
#define ABS(a) (a) < 0 ? -(a) : (a)

printf("abs of -1 and 1: %d %d", ABS(-1), ABS(1));

• Note: importance of parentheses


• In C99, you can create a macro with a variable number of
arguments.

151
#error
• Syntax:
#error error-message

• Forces the compiler to stop compilation.


• Used primarily for debugging.
• The error-message is not between double quotes.

152
Conditional Compilation Directives
#if constant-expression
statement sequence
#endif
#if expression
statement sequence
#elif expression 1
statement sequence
#elif expression 2
statement sequence
#elif expression 3
statement sequence
#elif expression 4
...
#elif expression N
statement sequence
#else statement sequence
#endif

153
Conditional Compilation Directives (cont.)
#ifdef macro-name
statement sequence
#endif

#ifndef macro-name
statement sequence
#endif
• Using defined:
#if defined macro-name
statement sequence
#endif

#if ! defined macro-name


statement sequence
#endif

154
#line
• Changes the contents of __LINE__ and __FILE__, which are
predefined identifiers in the compiler:
• The __LINE__ identifier contains the line number of the currently
compiled line of code.
• The __FILE__ identifier is a string that contains the name of the source
file being compiled.
#line number "filename"

• The file identifier filename is optional.

155
The # and ## Preprocessor Operators
• Are used with the #define statement.
• The # operator, which is generally called the stringize operator,
turns the argument it precedes into a quoted string.
#define mkstr(s) #s
/* ... */
printf(mkstr(I like C));
printf("I like C");

• The ## operator, called the pasting operator, concatenates two


tokens.
#define concat(a, b) a ## b
/* ... */
int xy = 10;
printf("%d", concat(x, y));
printf("%d", xy);

156

You might also like