7 CPS393 IntroC

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 100

C/CPS 393

Introduction to UNIX, C and C++


Prof. Alex Ufkes

Topic 7: Intro to C
Notice!

Obligatory copyright notice in the age of digital


delivery and online classrooms:

The copyright to this original work is held by Alex Ufkes. Students


registered in course C/CPS 393 can use this material for the purposes
of this course but no other use is permitted, and there can be no sale
or transfer or use of the work for any other purpose without explicit
permission of Alex Ufkes.

© Alex Ufkes, 2022 2


Course Administration

Midterm #2, covering all Linux material,


takes place in your lab on Nov 2/3

© Alex Ufkes, 2022 3


Today

Intro to C:
Variables
Functions
Control flow

© Alex Ufkes, 2022 4


© Alex Ufkes, 2022 5
What, Why, When, Who?

Dennis Ritchie & Ken Thompson


Bell Labs, 1972-1973
Wanted to write utilities for Unix
This was early Unix, being developed
in Assembly at the time.
Later, C was used to re-implement
the entire Unix kernel.
One of the first kernels implemented
in something other than Assembly!

© Alex Ufkes, 2022 6


What, Why, When, Who?

C was one of the early general-purpose programming languages.

Meaning:

FORTRAN FORmula TRANslation


Turn mathematical formulas into code
COBOL COmmon Business Oriented Language
Designed for business, finance use
ALGOL Meant for algorithm description

© Alex Ufkes, 2022 7


What, Why, When, Who?

Why teach C?

C is relatively small (32 reserved words)


C is common
C is stable (well established language,

C is efficient at runtime
C is the basis for other languages (e.g. C++)
C is (relatively) easy to learn.

© Alex Ufkes, 2022 8


What, Why, When, Who?

%:
"

© Alex Ufkes, 2022 9


Hello, world!

#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return (0);
}

© Alex Ufkes, 2022 10


Compiling C in Linux

Use gcc: → compiling


C
fries

out .

to
stand art
writes

give yourself execution permission

/
a

© Alex Ufkes, 2022 11


Compiling C in Linux

Use o option to specify executable name:

© Alex Ufkes, 2022 12


Redirection

Same as Linux!

The printf function writes to stdout

© Alex Ufkes, 2022 13


Digging Deeper: Hello, world!

Pre-processor directive ?
#include <stdio.h> function prototype
int main(void) or signature
{
main
printf("Hello, world!\n");
function
return (0);
Semi-colon terminates C statements
}

Curly braces indicate scope of main function


© Alex Ufkes, 2020, 2021 14
Compilation Stages

1. 3. Compiler

Source Code (C)

2.
4. Executable
Preprocessor (machine code)
© Alex Ufkes, 2020, 2021 15
Preprocessor Directives

The preprocessor modifies your C source


code prior to compilation.
Preprocessor directives begin with #
There are many different directives, but in

#include and #define

© Alex Ufkes, 2020, 2021 16


© Alex Ufkes, 2020, 2021 17
Preprocessor Directives: #include

#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return (0);
}
What does stdio get us?
Many things! one of which
is the printf function

© Alex Ufkes, 2020, 2021 18


Preprocessor Directives: #define

#define acts as a search-and-replace macro:

#include <stdio.h>
#define TEXT "Hello, world!\n"
int main(void)
{
printf(TEXT);
return (0);
}

© Alex Ufkes, 2020, 2021 19


Preprocessor Directives: #define

help
caps
#include <stdio.h>
#
All
to
read your
better
#define HELLO main code
see
anywhere
if you
#define SAY printf else ,
you
can guess
a
define
it is

int HELLO(void) Macro

{
SAY("Hello, world!\n");
return (0); This makes perfect sense when you
understand how #define works.
}
It just obfuscates your code.
© Alex Ufkes, 2020, 2021 20
Preprocessor Directives: #define

A far better use for #define:

#include <stdio.h> This a good use of #define.


#define PI 3.14159265359 Numerical or physical
constants that never change.
int main(void) Once something is #defined,
{ it cannot be changed later.
printf("Hello, world!\n"); #defined values are fixed at
return (0); compile time.
} Convention is to use CAPS

© Alex Ufkes, 2020, 2021 21


Comments

#include <stdio.h>
/* define PI */ Comments can be used to
#define PI 3.14159265359 explain your code to other
programmers
int main(void) /* main function */
They can also serve as
{
reminders for the original
/* Say hello */
programmer.
printf("Hello, world!\n");
They are NOT compiled.
return (0);
}

© Alex Ufkes, 2020, 2021 22


Statements & Semicolons

In C, statements are terminated with a semicolon:


not
they
are
We don't put semi - colons after pre -

processor ,

?
a statement .

#include <stdio.h>
int main(void)
{
printf("Hello, world!\n"); /* printf
statement */
return (0); /* return
} statement */

© Alex Ufkes, 2020, 2021 23


Line Breaks? Spaces? Tabs?

However

#include <stdio.h>
#include <stdio.h>
int main(void)
int main(void) {
{
printf("Hello, world!\n");
printf("Hello, world!\n");
return (0) ;}
return (0);
}

One of these is much easier to read.


Readability is important.

© Alex Ufkes, 2020, 2021 24


© Alex Ufkes, 2020, 2021 25
© Alex Ufkes, 2020, 2021 26
© Alex Ufkes, 2020, 2021 27
E-E.io/**qeEEItK--zu- Variable Declaration Basketkolik
→www.ew

Like Java, C is statically typed:

#include <stdio.h>
int main(void) ?
{
int wholeNum; // Reserve memory for int
double realNum; // Reserve memory for double
char charValue; // Reserve memory for char
return (0);
}

© Alex Ufkes, 2020, 2021 28


Memory?

Computer memory:
A collection of consecutively
numbered cells
Each cell is typically one byte
One byte == 8 bits

© Alex Ufkes, 2020, 2021 29


Variables in Memory

char c; /* 1 byte allocated */


int wholeNum1; /* 4 bytes allocated */
double realNum2; /* 8 bytes allocated */

c wholeNum1 realNum2

1 byte 4 bytes 8 bytes

© Alex Ufkes, 2020, 2021 30


More on Memory

This is handled by the compiler, assembler and OS


Later, we will see how to use pointers to manipulate our

Remember: Think of variables as containers in memory.

its location in memory.

© Alex Ufkes, 2020, 2021 31


AHH.mx#:-*--A**.**l
Ed
Variable Types in C

→←É:¥Ét*÷t¥É*÷µ
Name Description Size* Range*
☆→
25
A
char Character 1 byte
signed: -128 to 127
unsigned: 0 to 255
short int signed: -32768 to 32767
Integer (short)
Short Integer. 2 bytes
unsigned: 0 to 65535
types
signed: -2147483648 to 2147483647
int Integer. 4 bytes
unsigned: 0 to 4294967295
long long signed: -2^63+1 to +2^63-1
Floating- Long integer. 8 bytes
int unsigned: 2^64 - 1
point float Floating point number. 4 bytes +/- 3.4e +/- 38 (~7 digits)
types Double precision
double 8 bytes +/- 1.7e +/- 308 (~15 digits)
floating point number.

(*depends on OS)
© Alex Ufkes, 2020, 2021 32
short int signed: -32768 to 32767
Short Integer. 2 bytes
(short) unsigned: 0 to 65535
signed: -2147483648 to 2147483647
int Integer. 4 bytes
unsigned: 0 to 4294967295
signed: -2^63+1 to +2^63-1
long long int Long integer. 8 bytes
unsigned: 2^64 - 1

© Alex Ufkes, 2020, 2021 33


The obvious:
Space is very limited on embedded systems
You should represent data as efficiently as possible

The not-so-obvious:

Multi-

© Alex Ufkes, 2020, 2021 34


Literals in C

Numeric literals:
5, -7, 42 (signed integer, whole numbers)
3.1415, -99.9 (floating point, real numbers)

Character literals: Indicated by single quotes


\

String literals: Indicated by double quotes


\

© Alex Ufkes, 2020, 2021 35


printf

print-formatted

int number = 15;


printf( \n , number);

Everything inside the %d is a placeholder. It


Beyond the quotes, after a
quotes gets printed to means, here we want to
comma, is the name of the
the screen, though not print the value of a variable.
variable we want to print.
exactly as it appears. Specifically, %d is for integer.

© Alex Ufkes, 2020, 2021 36


Characters as Integers?

#include <stdio.h>
int main(void)
{
int num1 = 84;
char
printf( \n , c1);
printf( \n , num1);
return (0);
}

© Alex Ufkes, 2020, 2021 37


Characters as Integers?

#include <stdio.h>
int main(void)
{
int num1 = 84;
char
printf( \n , c1);
printf( \n , num1);
return (0);
}
When we print a char as an int, we get the ASCII value
When we print an int as a char, we get the
corresponding character.
© Alex Ufkes, 2020, 2021 38
Formatting Placeholders
→recent

~É*r←*ax
int temp = 9;
printf( \n , temp);
%5d Reserves 5 places (right-justified)

Output
It is _ _ _ _ 9 degrees
4 spaces (not underscores), one spot for the number
© Alex Ufkes, 2020, 2021 39
Formatting Placeholders

Literal!
printf( -8d.\n , 1234);
%-8d reserves 8 places (left-justified)

Output
Number is 1 2 3 4 _ _ _ _.

4 spots for the number, 4 spaces after

© Alex Ufkes, 2020, 2021 40


Formatting Placeholders

int num = -38;


printf( \n , num);

Output
___-38

The negative sign takes


up a position!
© Alex Ufkes, 2020, 2021 41
More Placeholders

Seen: %d decimal (int)


Also: %f floating-point (float)
%lf long floating-point (double)
%c character (char)
%s string

Common pitfall:
d is for decimal, not double.
Use %d for int, %lf for double.

© Alex Ufkes, 2020, 2021 42


Formatting Floating-Point (double/float)

double num = 1.21997;


printf( lf , num);
ef default is 6

%lf placeholder for double

Output
1.219970

© Alex Ufkes, 2020, 2021 43


1) %lf
#include <stdio.h> Default format (6 decimal places)
int main(void) 2) %.2lf
{ Two decimal places (it rounds!)
double num = 3.1415; 3) %8.2lf
Two decimal places, right justify
/*1*/ printf( lf\n , num); using 8 spaces total.
/*2*/ printf( \n , num); 4) %.6lf
/*3*/ printf( \n , num); Six decimal places, right justify
/*4*/ printf( \n , num); 5) %-8.2lf
/*5*/ printf( -8.2lf\n , num); Two decimal places, left justify
/*6*/ printf( -.3lf\n , num); using 8 spaces total.
return (0); 6) %-.3lf
} Three decimal places, left justify

© Alex Ufkes, 2020, 2021 44


1) %lf
Default format (6 decimal places)
2) %.2lf
Two decimal places (it rounds!)
3) %8.2lf
Two decimal places, right justify
using 8 spaces total.
4) %.6lf
Six decimal places, right justify
5) %-8.2lf
Two decimal places, left justify
using 8 spaces total.
6) %-.3lf
Three decimal places, left justify

© Alex Ufkes, 2020, 2021 45


Many Variables, One printf
#include <stdio.h>
int main(void)
{
double num1 = 3.1415;
int num2 = 37;
char c1
char c2
char c3
printf( corld%c\n , c1, c2, c3);
printf( \n%.2lf\n , num2, num1);
return (0);
} Placeholders
© Alex Ufkes, 2020, 2021 46
Mismatched Placeholders

int number = -27;


printf( , number);
Here, we are printing an integer variable using a float placeholder.
In memory, the binary bit pattern represents an integer.
printf to read it as a float (%f)
Integer and float are represented very differently in binary!

This is not a syntax error!


This code will run, but it will print the wrong value.

© Alex Ufkes, 2020, 2021 47


Mismatched Placeholders

© Alex Ufkes, 2020, 2021 48


Declare large 64-bit integer

Print as int, print as double

The 2s comp bit pattern was read as


an IEEE 754 double.
(The integer constant was deliberately
picked to produce a bit pattern that
would yield 1.000000 as double)
© Alex Ufkes, 2020, 2022 49
User Input

© Alex Ufkes, 2020, 2021 50


scanf

Used to read from standard input (keyboard by default)

int number;
scanf( , &number);
Syntactically: Very similar to printf

Two key differences:


1) Do not use placeholder formatting provide placeholders only
2) Instead of providing a variable to print, we provide the address
of a variable to write to. This is done using the & operator.

© Alex Ufkes, 2020, 2021 51


scanf

These are two of the most common errors:

You may be tempted to do one or more of the following:

scanf( , &intVar);
scanf( \ , &intVar);
scanf( , &doubleVar); BAD! Use placeholder only

BAD!
scanf( , intVar);
scanf( , doubleVar);

© Alex Ufkes, 2020, 2021 52


Bad, But Why?

scanf( , &intVar);
scanf( \ , &intVar); Not a syntax error!
scanf( , &doubleVar);
The content inside the quotes tells scanf what it is going to read in.
If you write , scanf will expect to read the

Instead, do this as follows:

printf(
scanf( , &intVar);
);
GOOD!
© Alex Ufkes, 2020, 2021 53
Bad, But Why?

scanf( , intVar);
scanf( , doubleVar); Not a syntax error!

scanf needs an address to know where in memory it will write the value. This
is what the & gets us.
If you do not provide the address of the desired variable, but rather just the
value of the variable, your program will attempt to write the scanned value at
the address equal to the value of the provided variable (almost never correct).

© Alex Ufkes, 2020, 2021 54


Address VS Value

Remember:
Memory is a sequence of
consecutively numbered cells.
scanf needs the cell number,
or the address. 01010101
Using & gets us the address 01001001
11100111 Scanf
NOT 00000000 needs
this! this!

© Alex Ufkes, 2020, 2021 55


Scanning Multiple Variables?

Not ideal, but can be done:

#include <stdio.h>

int main(void)
{
int age;
double height;

printf("Enter your age and height: ");


scanf("%d%lf", &age, &height);

printf("You are %d years old\n", age);


printf("You are %lf feet tall\n", height);
return (0);
}
© Alex Ufkes, 2020, 2021 56
Do This Instead

#include <stdio.h>

int main(void)
{
int age;
double height;

printf("Enter your age: ");


scanf("%d", &age);

printf("Enter your height: ");


scanf("%lf", &height);

printf("You are %d years old\n", age);


printf("You are %lf feet tall\n", height);
return (0);
}
© Alex Ufkes, 2020, 2021 57
Arithmetic Expressions

© Alex Ufkes, 2020, 2021 58


Unary Operators

Unary: One operand Important!


Unary Plus (+) +2 = 2 Stored value of x
Unary Minus (-) -(-2) = 2

int x = -3; Output?


printf( \ , x); x = -3
printf( -x = %d\ , -x); -x = 3
printf( \ , +x); +x = -3

© Alex Ufkes, 2020, 2021 59


Binary Operators

Addition (+)
3 + 4 or 55.1 + 43.58
Subtraction (-)
Binary as in two operands.
50 - 20 or 45.3 - 0.78
Not binary code.
Multiplication (*)
5 * 10 or 0.6 * 3.4
Division (/)
Only works on integers! 50.0 / 2.0 or 45 / 2
Remainder (%)
30 % 7 or 45 % 3 or 23 % 77
© Alex Ufkes, 2020, 2021 60
Integer Expressions

An arithmetic expression containing only integers.


The result of an integer expression is always integer.
Non-integer results are truncated.

int x = 99, y = 100;


Two integers!
double result; Truncation occurs *before*
result = x/y; being stored in result!
printf( lf\ , result);

Output? x/y = 0.000000


© Alex Ufkes, 2020, 2021 61
Floating-Point Expressions

An arithmetic expression containing only floating-point types.


The result of a double expression is always double.

double x = 99, y = 100, result;


Two doubles!
result = x/y;
Result will be double.
printf( lf\ , result);

Output? x/y = 0.990000

© Alex Ufkes, 2020, 2021 62


Mixed Expressions

An arithmetic expression containing both floating-point and integers.


The result of a mixed expression yields floating point.

int x = 5;
double y = 2.0, r1, r2; Output?
r1 = x*y;
r2 = x/y; x*y = 10.000000
printf( lf\ , r1); x/y = 2.500000
printf( lf\ , r2);

© Alex Ufkes, 2020, 2021 63


Typecasting

Convert a value of one type to another:

int x = 99, y = 100;


double result;
result = x/y; Output?
printf( lf\ , result); x/y = 0.000000
result = (double)x/y;
printf( lf\ , result); x/y = 0.990000

© Alex Ufkes, 2020, 2021 64


Be Careful!

int x = 99, y = 100; Output?


printf( lf\ , x/y); 0.000000
printf( lf\ , (double)x/y); 0.990000
printf( lf\ , x/(double)y); 0.990000
printf( lf\ , (double)(x/y)); 0.000000

Parentheses are evaluated first!


Result gets truncated before the cast occurs!

© Alex Ufkes, 2020, 2021 65


Shortcut Operators

i += 1; /* i = i + 1; */
a /= 2; /* a = a / 2; */
x *= 5; /* x = x * 5; */
i++; /* i = i + 1; */
++i; /* i = i + 1; */
i--; /* i = i - 1; */
--i; /* i = i - 1; */

© Alex Ufkes, 2020, 2021 66


Careful!

r = ++x; NOT the same as r = x++;

int x = 2, y = 2, r1, r2;


r1 = ++x; Output?
r2 = y++; pre = 3
printf( \ , r1);
printf( \ , r2);
post = 2

Pre-increment: increment, then evaluate/assign.


Post-increment: evaluate/assign, then increment.

© Alex Ufkes, 2020, 2021 67


math.h

math.h, like stdio.h, is part of the C standard library.


We include it in the same way using a preprocessor directive:

#include <math.h>
Recall:
Including stdio.h lets us use various I/O functions
printf, scanf

Including math.h gets us many useful math functions:


sqrt, log, exp, pow, sin, cos, tan, and more.

© Alex Ufkes, 2020, 2021 68


© Alex Ufkes, 2020, 2021 69
Greater than (>) Less than (<)
4 > 3 True -4 < 4 True
5 > 5 False 5 < 5 False
Greater than or equal to (>=) Less than or equal to (<=)
3.1 >= 3.1 True -1 <= 0 True
5 >= 6 False -1 <= -2 False
Equality (==) Not equal (!=)
7 == 7 True 3 != 4 True
-1 == 1 False 5 != 5 False
© Alex Ufkes, 2020, 2021 70
The NOT Operator

True when operand is false, false when operand is true

!
x !x
1 0
0 1
© Alex Ufkes, 2020, 2021 71
The AND Operator

True when both operands are true

x y x && y

&& 1
1
0
0
1
0
1
0
1
0
0
0
© Alex Ufkes, 2020, 2021 72
The OR Operator

True when at least one operand is true

x y x || y

|| 1
1
0
0
1
0
1
0
1
1
1
0
© Alex Ufkes, 2020, 2021 73
Branching

© Alex Ufkes, 2020, 2021 74


The if Statement

/* single branch, same as Java */

if (condition)
condition is true, execute statement;

© Alex Ufkes, 2020, 2021 75


int temp;
printf( );
scanf( , &temp);
if (temp >= 100)
{
printf( \ );
}

Input: Output:
107 The water is boiling!
24

© Alex Ufkes, 2020, 2021 76


The if Statement

/* double branch, same as Java */

if (condition)
condition is true, execute statement;
else
condition is false, execute statement;

© Alex Ufkes, 2020, 2021 77


int temp;
printf( );
scanf( , &temp);
if (temp >= 20) {
printf( \ );
}
else {
printf( \ );
}
Input: Output:
17 It is cool outside
24 It is warm outside
© Alex Ufkes, 2020, 2021 78
The if Statement

Nested if statements? Same as Java.


Else/if ladders? Same as Java.
Curly braces for the body? Same as Java.
One statement rule? Same as Java.

Seeing a pattern? Control structures in C


are almost exactly the same as Java.

© Alex Ufkes, 2022 79


switch
Statements

© Alex Ufkes, 2020, 2021 80


switch(control_value)
{
case value1:
/* statement(s) */
break; Notice:
case value2: These are colons!
/* statement(s) */ Not semi-colons.
break;
case value3:
/* statement(s) */
break;
default:
/* statement(s) if no case value
matches the control value */
}
© Alex Ufkes, 2020, 2021 81
int control = 0;
If control == 0,
switch(control)
{ Execute the following statements:
case 0:
/* statement(s) */
The break keyword exits the
break;
case 1: switch control structure
/* statement(s) */
break;
case 2:
/* statement(s) */ Does not
break;
default: execute!
/* statement(s) if no case value
matches the control value */
}

© Alex Ufkes, 2020, 2021 82


if (control == value1)
{
switch(control) /* statement(s) */
{ }
case value1: else if (control == value2)
/* statement(s) */ {
break; /* statement(s) */
case value2: }
/* statement(s) */ else if (control == value3)
break; {
case value3: /* statement(s) */
/* statement(s) */ }
break; else
default: {
/* statement(s) if no /* statement(s) if no
value matches control */ value matches control */
} }
© Alex Ufkes, 2020, 2021 83
char colour
We can have multiple cases per outcome.
switch(colour)
{
case
case No match!
printf( );
break; Output?
case
No match!
case
printf( );
Go!
break;
case Match
case
printf( );
break;
default: Does not
printf( colour ); execute!
© Alex Ufkes,}2020, 2021 84
char
switch(value)
{
case
printf(
case
); Output?
printf( );
case A B C D E Default
printf( );
case We forgot the breaks! Once we
printf( ); enter a case, everything below gets
case executed UNLESS we use a break to
printf( );
exit the switch.
default:
printf( );
}
© Alex Ufkes, 2020, 2021 85
Loop Structures

© Alex Ufkes, 2020, 2021 86


1) for loop
2) while loop
3) do/while loop

© Alex Ufkes, 2020, 2021 87


int i;
condition

for (i = 1; i <= 3; i++)


{
Loop
printf( \ );
body
}
Exit loop
Order of execution: False

initialization condition True body update

© Alex Ufkes, 2020, 2021 88


Write code snippet using a for loop to do the following:
Calculate the factorial of a number inputted by the user.

int num, i, fact = 1;


printf( );
scanf( , &num);

for ( i = 1; i <= num; i++ )


Finally,
{ Print the result.
fact = fact * i;
}
printf( \ , num, fact);
© Alex Ufkes, 2020, 2021 89
1) for loop
2) while loop
3) do/while loop

© Alex Ufkes, 2020, 2021 90


int n = 1; /* initialize */
while (n <= 2) /* condition */
{
printf( \ , n);
n = n + 1; /* update */
}
Unlike a for loop, a while loop only requires that
we provide a condition for it to compile.
We must be very careful to include the initialization
and the update steps on our own.

© Alex Ufkes, 2020, 2021 91


1) for loop
2) while loop
3) do/while loop

© Alex Ufkes, 2020, 2021 92


while VS do/while

while (condition) { Condition checked at the start.


/* statements */ If condition is initially false, body
} never executes.

Condition checked at the end. do {


If condition is initially false, /* statements */
body will still execute once. } while (condition);

The body of a do/while loop will execute at least once.


© Alex Ufkes, 2020, 2021 93
Write code snippet to do the following:
Read in numbers until a negative value is entered.

int value;

do {
printf(
printf( ); );
scanf(
scanf( , &value);
, &value);
}
while ( value >= 0 );

© Alex Ufkes, 2020, 2021 94


How do I decide?

© Alex Ufkes, 2020, 2021 95


Use when the number of
for loop iterations is known in advance.
int i;
for (i = 1; i <= 5; i++) {
printf( \ );
}

A for loop conveniently integrates the initialization,


condition, and update steps into a single line.
© Alex Ufkes, 2020, 2021 96
do/while loop
Use when the loop body must execute at least once.

int value;
do {
printf( );
scanf( , &value);
} while (value >=0);

A do/while loop is ideal for input validation.


© Alex Ufkes, 2020, 2021 97
while loop Use in all other situations.

int n = 1;
while (n <= 2) {
printf( \ , n);
n = n + 1;
}

A while loop can be adapted to any looping task.


© Alex Ufkes, 2020, 2021 98
A Loop is as Loop is a Loop

If the task can be solved with a while loop, it can also be


solved with a for loop, and so on.

By adjusting initializations, conditions, and updates, every loop


can be tweaked to be the functional equivalent of another.

This is fantastic practice! Try solving a looping


problem with each of three loop styles.

© Alex Ufkes, 2020, 2021 99


© Alex Ufkes, 2022 100

You might also like