Title: April 2004
1Sticky Bits in C
- Diverse topics of interest and confusion to new
users of the C programming language - Topics include
- Control structures
- Variable types
- Pointers!
- Arrays and structs
- Linked lists
- Recursion
- Debugging
2Sticky Bits in C
Control Structures
3Control Structures
- Sequential
- Assignment statements
- Selection
- if / if else
- switch
- Test determines execution of clause
- Else condition or default case used for execution
only on test failure - No guaranteed execution of clause following if
or switch
- Iteration (Repetition)
- for
- while / do while
- Loop conditions at end or beginning of iteration
- Index can control the number of iterations
- No minimum number of iterations
- Recursion is a form of iteration
4Sticky Bits in C
Variable TypesAnd Pointers!
5Data Types
- Pointer variables hold addresses
- Pointers have a base type of any legal C type
including another pointer. Examples - long (pointer-to-long-int)
- float (pointer-to-float)
- int (ptr-to-ptr-to-int)
- char (ptr-to-char / string)
- double (ptr-to-ptr-to- ptr-to-ptr-to-ptr-to-
double) - You get the idea
- Variables hold values
- Integer types
- long int (or long)
- int
- short int (or short)
- char (itty-bitty integer)
- Floating point types
- long double
- double
- float
6Pointer Variable Notes
- The asterisk
- Dereferencing operator
- Defines a pointer type in a declaration, e.g. int
- Dereferences a pointer vairable to get the
contents at the address pointed to, when used in
a statement, e.g. ptrnum - The ampersand
- Addressing operator
- Retrieves the address of a variable, e.g.
othernum
- How To
- Declare a pointer variable
- int ptrnum
- Assign an address to a pointer variable
- ptrnum num
- Retrieve the value in the address that a pointer
points to (and saving it) - othernum ptrnum
7Using Pointers to Allocate Space
- The computer gives your program memory when you
declare variables. - YOU can give your program more memory by using
pointer variables! - You can request additional memory space by using
malloc or calloc with a pointer variable
- int tenspaces / this is just
the pointer, not the actual spaces / - tenspaces (int ) malloc ( 10 sizeof (int) )
- / cast to int , the address of 10 integer
sized memory locations / - / Now you can put stuff in those spaces /
- tenspaces0 42
- (tenspaces 1) 1024
- for (i2, i lt 10, i)
- tenspacesi i
8Sticky Bits in C
Recursion
Recursion
Recursion
Recursion
Recursion
Recursio
Recurs
9Recursion Development
- Recursive functions typically implement
recurrence relations which are mathematical
formula in which the desired expression
(function) involving a positive integer, n, is
described in terms of the function applied to
corresponding values for integers less than n.
Foster Foster, C by Discovery - The function written in terms of itself is a
recursive case - The recursive case must call the function with a
decreasing n - Initial conditions or starting values for the
function must also be given. This is used as the
termination condition for the recursive function. - The function with a defined output value for a
specific input is a base case
10Recursion - Example
- Fibonacci Sequence
- 1, 1, 2, 3, 5, 8, 13, 21,
- 1st 2nd 3rd 4th 5th 6th 7th 8th
- Let us call the 1st Fibonacci number, Fib(1), the
2nd Fib(2) This gives us n. - Fib(1) 1 defined base case
- Fib(2) 1 defined base case
- Fib(3) 2 1 1
- Fib(2) Fib(1)
- Fib(7) 13 8 5
- Fib(6) Fib(5)
- Fib(n) Fib(n-1) Fib(n-2)
- Fibonacci Algorithm using Recursion
- int Fib (int n)
-
- int temp 1 / handles base cases /
- if (n gt 2)
- temp Fib(n-1) Fib(n-2)
- return temp
It should be noted that one of the most difficult
things about recursion with Fibonacci is the
magical decision to number the Fibonacci elements
and then to use that number as n. This is akin
to mathematical proofs where the author says So
now we let k stand for amrpt
11Recursion - What is it doing!?_at_!
- int FibCaller(void)
-
- int fibval5
- if (fibval gt 0)
- fibval Fib(fibval)
-
- int Fib (int n)
- / handles base cases of /
- / Fib(1) and Fib(2) /
- int temp 1
- if (n gt 2) / other cases /
- temp Fib(n-1) Fib(n-2)
- return temp
Fib(5) 5
5
Fib(3) 2
Fib(4) 3
2
Fib(2) 1
Fib(1) 1
Notice that the recursion isnt finished at the
bottom -- It must unwind all the way back to the
top in order to be done.
3
Fib(3) 2
Fib(2) 1
2
Fib(2) 1
Fib(1) 1
12Recursion - Should I or Shouldnt I?
- Pros
- Recursion is a natural fit for some types of
problems
- Cons
- Recursive programs typically use a large amount
of computer memory and the greater the recursion,
the more memory used - Recursive programs can be confusing to develop
and extremely complicated to debug
13Sticky Bits in C
Arrays and Structs
14Aggregate Data Structures
- Arrays combine many pieces of data into one
structure which is easy to access. - All of the data elements in an array must be of
the same type - Structs combine many pieces of data into a single
data type - The data elements of the struct can be of
different types - Data elements are accessed by variable name and
selected by member name
15Aggregate Data Types - Structures
- Hold multiple data values
- Group multiple data types
- Ex UTA student data
- Student ID number
- Last name
- First name
- GPA
- Major
- Structure - keyword struct
- Defines an aggregate type member subcomponents
- struct uta_student
- unsigned ID_num
- char last_name,
- first_name
- float GPA
- char major4
U,N,D,E -
16Structure Operations and Member Accessing
- To access a component of a structure, a variable
(for ex. stdt_1)of the struct type must be
declared. Then the components of that variable
are accessed with the selector(.) construct. - The ANSI standard operations that work on
structures are - Select members
- Assign the contents of one structure variable to
another - Address () structure variables
- Sizeof() structure variables
- / variable declaration /
- struct uta_student
- stdt_1, stdt_2, stdt_ptr
- stdt_1.ID_num 608469999
- stdt_1.last_name Smith
- stdt_1.first_name Snuffy
- stdt_1.GPA 2.15
- stdt_2 stdt_1 / struct assignment /
- stdt_ptr stdt_2 / struct pointer /
- int stdt_sizesizeof(struct uta_student)
-
17Arrays and Pointers and Structures Oh My!
- An array of structures means that each element of
the array is an entire structure. Ex - struct uta_student cse13203
- cse1320 points to head of the array
- cse13202 is the third structure (element) in
the array - cse13202.ID_num is the id_num member of the
third structure - cse13202.major0 is the first letter of the
major
- A pointer to a structure is typically used when
structures are allocated dynamically such as in a
linked list. Structures may also contain
pointers as structure members. - struct uta_student new_stdt
- new_stdt can hold the address of a uta_student
structure - (new_stdt).ID_num or new_stdt-gtID_num is the
id_num for the struct the new_stdt points to
ID_num last_nm first_nm GPA major4 major4 major4 major4
654903211 Luitania Marta 3.4 P C S E
000003789 Axel Rose 4.0 E E D
744521111 Tibi Imad 3.95 M A T H
18Sticky Bits in C
Linked Lists
19Data Structures built with Structs
- Multi-element storage structures are created from
individual structs - Each struct must be able to point to another
struct of the same type - struct uta_student
- unsigned ID_num
- char last_name,
- first_name
- float GPA
- char major4
- struct uta_student next_stdt
-
- The most common structure then is a linked list
in which each element of the list is a struct
which has at least one pointer linking it to
another struct in the same list. -
20Linked Lists
UTA
new
- A linked list is a good data structure to use
when the amount of data to be stored is unknown
or can fluctuate. - Building a simple unsorted singly-linked list
requires at least - Dynamic memory allocation to a struct pointer for
each new element (or node) to be added to the
list - A pointer to the head of the list
- A pointer that can travel through the list
elements
UTA
head
-gtnext_stdt
UTA
-gtnext_stdt
UTA
travel
-gtnext_stdt
21Linked Lists
- A singly-linked list is built by making a loop
that - Allocates a new list element and puts the new
data in it (from a file or from the user, etc.), - Determines where in the list the new element
should go beginning (head), middle or end of the
list, then - Adds the new element to the list
A list element might consist of a uta_student
struct with a last_name value of pi along with
other member values
UTA
pi
22Linking the List
- A singly-linked list is built by making a loop
that - Allocates a new list element and puts the new
data in it (from a file or from the user, etc.), - Determines where in the list the new element
should go beginning (head), middle or end of the
list, then - Adds the new element to the list
- Allocating a new struct in C means using malloc
or calloc to create space and assign it to a
pointer variable. Then values would be assigned
to the members of the struct. Ex
new (struct uta_student )malloc (sizeof
(struct uta_student)) new-gtlast_name pi /
other data initialized / (new).next_stdt NULL
23Linking the List
- Determining where the new element should go is
either - a) defined for the list, e.g. all new elements
go at the head of the list, or - b) it is determined by some kind of test or
comparison to each element in the list. - The travel pointer moves through the list
pointing to each element in turn. Ex
- A singly-linked list is built by making a loop
that - Allocates a new list element and puts the new
data in it (from a file or from the user, etc.), - Determines where in the list the new element
should go beginning (head), middle or end of the
list, then - Adds the new element to the list
/ in some sort of loop / if ( new-gtlast_name lt
travel-gtlast_name) / then new goes in
the list before travel / else travel
travel-gtnext_stdt
UTA
head
alpha
-gtnext_stdt
UTA
nu
-gtnext_stdt
UTA
phi
UTA
travel
tau
new
-gtnext_stdt
UTA
zeta
24Linking the List
- Adding an element to the list means hooking up
the pointers correctly. To put an element in the
middle of a singly-linked list takes the most
steps. Ex
- A singly-linked list is built by making a loop
that - Allocates a new list element and puts the new
data in it (from a file or from the user, etc.), - Determines where in the list the new element
should go beginning (head), middle or end of the
list, then - Adds the new element to the list
/ using the travel pointer and a follow pointer
which is one link behind the travel pointer / if
( new-gtlast_name lt travel-gtlast_name) /
insert node / new-gtnext_stdt
travel follow-gtnext_stdt new
25Doubly Linking the List
UTA
new
phi
- All the preceding applies to singly- linked
lists. In a doubly-linked list, each element
has pointers to the links before it AND after
it. Thus each element now contains - struct uta_student
- unsigned ID_num
- char last_name, first_name
- float GPA
- char major4
- struct uta_student prev_stdt,
next_stdt -
UTA
head
alpha
-gtnext_stdt
UTA
-gtprev_stdt
-gtprev_stdt
nu
follow
-gtnext_stdt
travel
UTA
tau
-gtprev_stdt
-gtnext_stdt
UTA
zeta
26 Doubly Linking the List
- Adding an element to the list means hooking up
the pointers correctly. To put an element in the
middle of a doubly-linked list takes the most
steps. - Example below / using the travel pointer and a
follow pointer which is one link behind the
travel pointer /
- A doubly-linked list is built by making a loop
that - Allocates a new list element and puts the new
data in it (from a file or from the user, etc.), - Determines where in the list the new element
should go beginning (head), middle or end of the
list, then - Adds the new element to the list
if ( new-gtlast_name lt travel-gtlast_name) /
insert node / new-gtnext_stdt
travel new-gtprev_stdt follow follow-gtnext_st
dt new travel-gtprev_stdt new
-gtprev_stdt
-gtprev_stdt
UTA
UTA
UTA
nu
phi
tau
-gtnext_stdt
-gtnext_stdt
follow
travel
new
27Sticky Bits in C
Debugging.Ugh.
28Debugging. Ugh.
- Approaches to writing code that is easier to
debug - Write small blocks of code, then compile them and
test them before writing another block - Small means less than a page - half a page is
better - When two choices exist for how to write
something, choose the one that is simpler for you - Obviously, some assignments will require other
choices but in any case, simpler to write usually
means simpler to document and simpler to
understand and fix if necessary - If you can write it without pointers it will
usually be easier to debug - But often less efficient ltthere are always
trade-offsgt - Put in comments and document the code as you go
- It reminds you why you made certain choices and
it helps others who may be helping you debug.
29Debugging. Ugh.
- Approaches to locating a bug in a program
- Print, print, print
- The only way to really find out what the program
does at every point - Comment out
- Reduce the complexity of the program by
commenting out large sections and checking bit by
bit to see what works - Insert early returns
- Execute smaller parts of the code. If it works,
move the return further along. If not, you
have more closely isolated the problem. - Arm yourself with info
- When asking for help, provide as much info as
possible to the person who is helping
30Debugging. Ugh.
- What could it mean when it
- Gives segmentation fault?
- Pointer problems - almost always you are trying
to access outside your program space or access
non-existent space - NOTE Segmentation faults can eat the output in
the output queue so sometimes you may be trying
to print info to locate the fault but the info
doesnt get to the screen because of the fault.
?????? - Wont run my function?
- Probably doesnt really get to the function call
at all. Check what is happening in the calling
routine. - Wont print the data I read in?
- Maybe it didnt really read it in at all - have
you checked the input function?