Title: CSC234 Lecture 12
1CSC-234 Lecture 12
- Pointers
- Multiple Function Calls
- Scope of Names
- Arguments to Function main()
- Least Coin Algorithm
2Todays Topics
- An introduction to arrays.
- An introduction to C strings.
- Command-line arguments.
- More than you ever wanted to know about pointers.
- Global vs. local variables and the concept of
scope. - Multiple function calls, both interpretations.
- Least coin algorithm for hw6b.c
3Introduction to Arrays
- An array is a collection of data of the same
type. An array has a name and a length (number of
items in the array), and represents a contiguous
(adjacent) block of memory locations. An example
declaration - int aiValue10
- An array element is a subscripted variable, one
which uses the index of operator () - aiValue3 42
- The integer in brackets is the array subscript,
or array index.
4The Joy of Arrays
- But wait, you ask, you declared an array of 10
elements, didnt you? - Yes, but the indices of those 10 elements start
at 0 and go through 9. Element 1 is aiValue0,
and element 10 is aiValue9. - The fourth element, aiValue3, has been assigned
the value 42.
5Array Index Out Of Bounds
- Array indices are not checked at compile time or
at run time, leading to interesting results. - aiValue10 coincides with iThis, aiValue11
with fThat, and aiValue12 with cThose.
6Introduction to C Strings
- In C, a string is an array of characters.
- Strings are null-terminated (so the compiler and
run-time know where the end of the string is). - The null termination makes the string one element
longer than the actual string. - The null terminator is \0 (zero).
- Hungarian notation is either sz for string
terminated by zero or simply ac for array of
characters, which is what it really is.
7Example of String
- String declaration
- char szName6 David
- Or
- char acName6 David
- Note that the null termination is automatically
appended to the string, so what is held in memory
is actually David\0, but that is only 6
characters. - Note also that acName2 is the letter v and
acName5 is the null termination, \0.
8Changing String Values
- We need include ltstring.hgt to use string
functions. - Strings are immutable, that is, they cannot
simply be changed via assignment - char szName20 John Doe (OK)
- Then
- szName Jane Smith (not OK)
- But
- strcpy (szName, Jane Smith) (OK)
- And
- scanf (s, szName) (OK)
- But only the first name will be accepted (stops
at white space). - Lesson To change a string within a program, use
strcpy().
9Comparing String Values
- You cannot say
- if (szName John Doe)
- You must say
- if (strcmp (szName, John Doe) 0)
- Which is not false, since strcmp() returns
- 0 if szName is equal to John Doe.
- lt0 if szName is less than John Doe.
- gt0 if szName is greater than John Doe.
- So, cat gt Cat, car lt cat, and care gt
car.
10Arguments to Function main()
- Up to now, we have treated main() as if it had no
arguments. In reality, it has two - void main (int argc, char argv)
- The first input argument is an int that
represents the argument count. - The second input argument is an array of pointers
to strings, or argument vectors.
11Command-Line Arguments
- Arguments to function main() are called
command-line arguments, and you have already
used them - gcc hw2a.c
- Here, there are three arguments, so argc 2,
and - argv0 gcc
- argv1 hw2a.c
- Yes, the command itself is the first argument.
12Why?
- Imagine what it would be like if you had
hard-coded values in a program, and had to
recompile the program every time those changed. - This way, we can override hard-coded values with
our own command-line values at run time.
13Where?
- Under DOS and earlier Windows versions (as well
as UNIX or Linux), we had to install a lot of
device drivers. Those needed to know an interrupt
number, a port value, a drive letter, etc. - By using command-line arguments, those could all
be passed in at run time - C\CDROM12X\MSCDEX /V /DCD003 /M10
- Where argc 4 and argv3 /M10
14Numbers Arent Always Numbers
- Now we have a mechanism to pass limits into our
temperature conversion program - a.out 200 200
- The new lower limit is argv1 (-200 in this
case) and the new upper limit is argv2 (200). - There is just one slight problem those numbers
arent numbers, they are strings! First we have
to convert these strings to numbers.
15atoi() and atof() in ltstdlib.hgt
- Within ltstdlib.hgt are a number of useful
functions including atoi() and atof(), which mean
ASCII to integer and ASCII to floating point. - They are prototyped as
- int atoi(str)
- double atof(str)
- Where str is a pointer to a string.
- Pointer to a string? That means
- char str
16Extracting Numbers
- if (argc 3)
-
- fLOWER (float) atof (argv1)
- fUPPER (float) atof (argv2)
-
- else if (argc ! 1)
-
- printf (Usage hw6a.exe lower upper\n)
-
- / end if argc /
- You either have to have no command-line arguments
or 3, hence the argc 3. - We pass argvn, a pointer to a string, to
atof(). - The else if clause is optional, but nice.
- This goes at the top of main() after the
declarations. Note that fLOWER and fUPPER can no
longer be declared as const, since we are
changing the value of them.
17UNIX Example
18DOS Example
19C vs. Machine Language
- First of all, it is often said that C is the
closest language to machine language, hence the
compact size and speed of applications programmed
in C. - One aspect of this is pointers. In machine
languages, there are address modes like
immediate (where the value to be used is held
in the following bytes) and indirect (where the
address of the location of the value to used is
held in the following bytes). C supports both of
these.
20Addressing Modes
- X 1 is an immediate assignment of 1 to the
variable X. - X Y indirectly assigns that value held by Y to
the variable X. - Also, indexed addressing uses the index register
to access an element of an array (machine
language is also 0-based).
21Pointers and Declaration
- A pointer is simply a special kind of variable
that can store the address of another variable. A
pointer variable - Has a name like any other variable.
- Has a type associated with it, the type of the
variable its address refers to. - A pointer declaration has an asterisk between the
data type and the variable name. - int piAdd
22Avoiding Ambiguity
- It does not matter where the asterisk goes, but
we typically place it immediately adjacent to the
variable name - int piAdd
- Not
- int piAdd
- The following declaration declares two pointers
and one plain variable - int piOne, iVar, piTwo
- Sanity and Style Tip Always declare pointers
separately, and one per line.
23The Overworked Asterisk
- The asterisk has three meanings
- The multiplication operator, used in arithmetic
expressions - iProduct iMult iQuot
- The indirection operator, used to declare
pointers - int piOne
- The dereferencing operator, used to get the value
stored at the address pointed to by the pointer - iVar piOne
- This is a valid expression that uses two of
these - iVar iTwo piOne
24Pointer Picture
- Given
- int iOne 1
- int iTwo 2
- int piAdd iTwo
25Assigning Values to Pointers
- A pointer must always point to something.
- We should really cover ourselves by initializing
pointers when we declare them - int piOne NULL
- Declares a null pointer.
- We can assign addresses to them within a program
- piOne iVar
- The is the address of operator here.
- We can equate two pointers also
- piOne piTwo
26Types of Variables
- Local variables are variables declared within a
block of code or function. - They may only be accessed within the function or
block of code in which they are initialized. - Global variables are variables declared outside a
function. - They are accessible to every function within the
source file.
27Global Variables, Source File
- Given
-
- int iOne 1
- void main (void)
-
- void DoThis (void)
-
- Variable iOne is global and accessible within
either function within this source file (inside
both sections).
28Global Variables, Header File
- Given file mystuff.h
- int iTwo
- void DoThis (void)
-
- void DoThat (void)
-
- ...
- Variable iTwo is also global. All functions
within this header file have access to this
variable. However, any file that uses include
mystuff.h also has full access to this variable
provided you use the extern keyword in any source
files that reference it - extern int iTwo
29Local Variables, Function
- Given
- void main (void)
-
- int iThree 3
-
-
- Variable iThree is a local variable, local to the
main() function. - It is accessible anywhere within the curly braces
of main(), but not accessible by other functions
in this (or any other) source file.
30Local Variables, Code Block
- Given
- for (int iLoop 1 iLoop lt 12 iLoop)
-
- Variable iLoop is a local variable, local ONLY to
the block of code delimited by the curly braces. - It is ONLY accessible within the for loop, not
outside of it.
31Variable Hierarchy, Setup
- Given
-
- int iLoop
- void main (void)
-
- int iLoop
-
- for (int iLoop 1 )
-
32Variable Hierarchy, Discussion
- The example shows a global variable (declared
outside main()), a local variable, and a loop
variable, all with the same name. - Within main(), its local variable supercedes the
global variable, so any reference to iLoop inside
main() (except inside the for loop) refers to the
local variable. - Inside the for loop, THAT local variable
supercedes BOTH the local variable in main() and
the global variable of the same name.
33Scope Picture
34Scopes of Names
- Scope is the word we use to describe the extent
over which variables (and constants) can be
accessed. - Local variables have local scope, the scope
encompasses the function or block of code in
which they are declared. - Global scope is similar.
35Multiple Function Calls
- There are two interpretations of this, one that
is used in the text, another that shows why we
write functions in the first place. - Section 6.5 is an example of a program with many
functions called by main(). We will also do this
in our upcoming homework assignments. - Another way of looking at this is a program that
calls the same function multiple times. This is a
good example of actual and formal parameters.
36One Function, Multiple Calls
- Once we cover strings, we will do a homework
assignment that relates to this, although the ATM
simulator assignment will also demonstrate this. - The following slide shows a main() function that
calls a function multiple times with different
local variables in main().
37Program Setup and Discussion
- The first time fDecay() is called, the value of
fTime1 is copied to fTime in the function. A
voltage is computed and returned as the function
name to the calling program which assigns this to
variable fVolt1. - The second time the function is called, the value
of fTime2 is copied to fTime, and the returned
value is assigned to fVolt2. - The third time is similar.
- float fDecay (float)
- void main (void)
-
- float fTime1, fTime2, fTime3
- float fVolt1, fVolt2, fVolt3
-
- fVolt1 fDecay (fTime1)
-
- fVolt2 fDecay (fTime2)
-
- fVolt3 fDecay (fTime3)
-
-
- float fDecay (float fTime)
38Whats Happening
- The function fDecay() needs a time from the
calling program, and returns a voltage. - The function call in main() passes a time to the
function, a time held by a local variable. - The functions returned value is assigned to
another local variable in main(). - Did we need three local variables in main() for
times and three for voltages? - If we are only going to use one time and one
voltage at a time, one local variable could have
been used three times. - However, if we are going to print out the three
times and the three voltages, we need all six
variables.
39Least Coin Algorithm
- This is pretty straightforward You start with
the largest coin and work down to the smallest,
ensuring that the least number of coins is
returned. - In the past few years, someone somehow proved
that we would need fewer coins if we replaced the
quarter with a 18 coin and the half dollar (that
no one uses anyway) with something like a 29
coin. (next slide)
4018 and 29 Coins
41Rounding Is An Issue
- We are working with float, and you will learn in
hw6b.c that rounding is a problem - 1.75 is stored as something like 1.7499876
- To deal with this, we add a phantom penny
- fAmt fAmt 0.01
- If you choose to return pennies, you need to add
half a penny - fAmt fAmt 0.005
42Integer Or Float?
- Working in integers rather than floats eliminates
a lot of the casting operations, but does nothing
else. - You will need an additional variable
- int iAmt 0
- You need to convert from float
- iAmt (int)((fAmt 0.01) 100.0)
- Then you simply work in integers.
43Method One Float
- fAmt fAmt 0.01
- piDoll (int)(fAmt / 1.00)
- fAmt fAmt (float)(piDoll) 1.00
- piQuar (int)(fAmt / 0.25)
- fAmt fAmt (float)(piQuar) 0.25
- And so forth.
- Remember to do the casting shown.
- Remember to dereference the pointers.
44Method Two Float
- fAmt fAmt 0.01
- while (fAmt gt 1.00)
-
- fAmt fAmt 1.00
- piDoll piDoll 1
-
- while (fAmt gt 0.25)
-
- fAmt fAmt 0.25
- piQuar piQuar 1
-
- And so forth.
- You need while(), not do-while(), and gt.
- piDoll does not work because of precedence.
- Note that the casting is eliminated.
45Method One Integer
- iAmt (int)((fAmt 0.01) 100.0)
- piDoll iAmt / 100
- iAmt iAmt (piDoll) 100
- piQuar iAmt / 25
- iAmt iAmt (piQuar) 25
- And so forth.
- Note that casting is eliminated, although
(int)(iAmt / 100) would be better. - Remember to dereference the pointers.
46Method Two Integer
- iAmt (int)((fAmt 0.01) 100.0)
- while (iAmt gt 100)
-
- iAmt iAmt 100
- piDoll piDoll 1
-
- while (iAmt gt 25)
-
- iAmt iAmt 25
- piQuar piQuar 1
-
- And so forth.
- You need while(), not do-while(), and gt.
- piDoll does not work because of precedence.
- Note that the casting is eliminated.
47Precedence Issues
- () grouping has the highest precedence.
- pre/post increment, dereference, and () type
cast have the next highest precedence and are
equal. - piDoll / is ambiguous /
- (piDoll) / might work /
- piDoll piDoll 1 / definitely works /
- multiplication and / division have the next
highest precedence and are also equal. - addition and subtraction are next and also
equal. - Be very careful!
48Incrementing A Dereferenced Pointer, Trial Number
1
- include ltstdio.hgt
- int main (void)
-
- int iOne 42
- int iThree 69
- int piTwo
- piTwo iThree
- printf ("Value is d.\n", piTwo)
- printf ("Address is d.\n", piTwo)
- piTwo
- printf ("Value is now d.\n", piTwo)
- printf ("Address is d.\n", piTwo)
- return (0)
49Result Number 1
- 130pm falcon gt gcc point.c
- 131pm falcon gt a.out
- Value is 69.
- Address is -4195424.
- Value is now 42.
- Address is -4195420.
- 131pm falcon gt
- What happened? The address was incremented, then
the pointer was dereferenced. (Not what we
wanted.)
50Incrementing A Dereferenced Pointer, Trial Number
2
- include ltstdio.hgt
- int main (void)
-
- int iOne 42
- int iThree 69
- int piTwo
- piTwo iThree
- printf ("Value is d.\n", piTwo)
- printf ("Address is d.\n", piTwo)
- (piTwo)
- printf ("Value is now d.\n", piTwo)
- printf ("Address is d.\n", piTwo)
- return (0)
51Result Number 2
- 137pm falcon gt gcc point2.c
- 137pm falcon gt a.out
- Value is 69.
- Address is -4195424.
- Value is now 70.
- Address is -4195424.
- 137pm falcon gt
- Now we dereference the pointer first, then
increment the value at that address. This is what
we wanted to do.
52Homework 6A Comments
- You need at least hw3a.c to base this on.
- Test it six times
- a.out
- Too low, too high, normal.
- a.out -200 200
- Too low, too high, normal
- Remember to change the prompt to display the
values of fLOWER and fUPPER so it properly
displays -200 and 200, rather than -100 and 500.
53Homework 6B Comments
- Follow your function handout and note that your
files should contain - The main program header.
- Preprocessor directives (include).
- Function prototype.
- Main() function.
- Function header.
- Function definition.
- Test it five times 1.00, 25, 10, 5, and
0.00.
54If You Are Bored or Canadian
- Modify the program to handle Canadian coinage.
- Quarters, dimes, nickels, and pennies are the
same. - The 1 coin is the Loonie, apparently the 2 coin
is the Twonie. - If you are feeling European, use Euros ().
- They have 1 and 2 coins.
- The other coins are 1, 2, 5, 10, 20, and 50.
- Current British coinage follows this, except they
have pounds () rather than Euros (). - Feeling masochistic? Try fractional British
coinage - ½ Farthing, Farthing, Halfpenny, Penny,
Threepence, Fourpence (Groat), Sixpence - Shilling, Florin, Half Crown, Crown,
- Quarter Guinea, Half Guinea, and Guinea.
- Oh, and the Pound, which is 20 Shillings.
- Invent your own coinage.
55Vending Machines Are Deadly
56Defective Cup Holder
57Stories
- NASA Space Shuttle Simulator.
- Overly friendly Pepsi machine.
- Most boring vending machine ever.
- Largest vending machine ever.
- About YOUR items
58Todays Lessons
- You should have a basic understanding of arrays
and strings. - You should be able to use command-line arguments.
- You should be able to use pointers.
- You should better understand formal and actual
arguments and how they relate. - You should know the difference between local and
global variables. - You should be able to do both hw6a.c and hw6b.c.