Professional Documents
Culture Documents
Programming
Lewis Girod
CENS Systems Lab
July 5, 2005
http://lecs.cs.ucla.edu/~girod/talks/c-
tutorial.ppt
1
or,
With extra
info in the
NOTES
2
High Level Question: Why is Software
Hard?
Answer(s):
• Complexity: Every conditional (“if”) doubles
number of paths through your code, every bit
of state doubles possible states
– Solution: reuse code with functions, avoid
duplicate state variables
3
Writing and Running Programs
#include <stdio.h>
/* The simplest C
Program */
int main(int argc, char
**argv)
1. Write text of program (source code)
{
printf(“Hello
using an editor such as emacs, save as
World\n”);
return 0;
file e.g. my_program.c
}
4
C Syntax and Hello World
#include <stdio.h>
The main() function is
/* The simplest C Program */ always where your
int main(int argc, char program starts
**argv) running.
{
printf(“Hello World\n”); Blocks of code
(“lexical scopes”) are
return 0;
marked by { … }
}
5
A Quick Digression About the Compiler
#include <stdio.h>
/* The simplest C
Program */
Compilation occurs in
int main(int argc, char
**argv)
Preprocess two steps:
{
printf(“Hello
“Preprocessing” and
“Compiling”
World\n”);
}
return 0;
Why
?
6
OK, We’re Back.. What is a Function?
Return type,
or void
Function
#include <stdio.h> Arguments
/* The simplest C Program */
int main(int argc, char
**argv)
{ Calling a Function: “printf()” is
just another function, like
printf(“Hello World\n”);
main(). It’s defined for you in
return 0; a “library”, a collection of
} functions you can call from
your program.
Returning a
value
7
What is “Memory”?
Initial value of x is
x 4 ?
char x;
char undefined y 5 ‘e’
y=‘e’;
(101)
The compiler puts
Initial 6
them somewhere
value
in memory. 7
Na
me What names are 8
legal?
9
Type is single
character (char) 10
extern? static?
const? 11
12 9
Multi-byte Variables
void p(char x)
Every Variable is Defined within {
/* p,x */
some scope. A Variable cannot be char y;
referenced by name (a.k.a. /* p,x,y
*/
Symbol) from outside of that scope. char z;
/* p,x,y,z
*/
}
Lexical scopes are defined with /* p */
curly braces { }. char z;
/* p,z */
void q(char a)
The scope of Function {
Arguments is the complete body char b;
/*
of the function. p,z,q,a,b */
{
The scope of Variables defined char c;
inside a function starts at the /*
char
p,z,q,a,b,c */
definition and ends at the } b?
closing brace of the containing char d;
block /* p,z,q,a,b,d (not
c) */ legal
} ?
The scope of Variables defined /* p,z,q */
outside a function starts at the
definition and ends at the end of
the file. Called “Global” Vars.
11
Expressions and Evaluation
1 + 2 * 2 1 + 4 5
(1 + 2) * 2 3 * 2 6
Not evaluated
because first
clause was true
12
Comparison and Mathematical Operators
+ & bitwise
Beware division:
plus and • If second argument is
- | bitwise integer, the
minus or
* ^ bitwise result will be integer
mult xor (rounded):
/ ~ bitwise
divide not 5 / 10 0 whereas 5 /
% << shift 10.0 0.5
modulo left
>> shift
• Division by 0 will cause a
right FPE
Don’t confuse & and &&..
1 & 2 0 whereas 1 && 2
<true>
13
Assignment Operators
14
A More Complex Program: pow
#include <stdio.h>
“if” statement #include <inttypes.h>
float pow(float x,
uint32_t exp)
{
/* if evaluated expression is not
/* base case */
0 */
if (exp == 0) {
if (expression) { Need return 1.0;
/* then execute this block */
braces? }
}
else {
X?Y: /* “recursive” case */
/* otherwise execute this block
Z return x*pow(x, exp –
*/
1);
}
}
Short-circuit detecting brace
eval? errors int main(int argc, char
**argv)
{
float p;
Tracing “pow()”: p = pow(10.0, 5);
printf(“p = %f\n”, p);
• What does pow(5,0) do? return 0;
}
• What about pow(5,1)?
• “Induction”
15
The “Stack”
17
The “for” loop
18
Referencing Data from Other Scopes
float pow(float x,
uint exp)
{
float result=1.0;
int i;
for (i=0; (i < exp);
i++) { Nothing in this scope
result = result *
x;
}
return result;
}
19
Can a function modify its arguments?
Would this
work?
void pow_assign(float x,
uint exp)
{
float result=1.0;
int i;
for (i=0; (i < exp);
i++) {
result = result * x;
}
x = result;
}
20
NO!
Remember the
stack!
Java/C+
void pow_assign(float x,
uint exp) +?
{ In C, all arguments
float result=1.0;
int i; are passed as
for (i=0; (i < exp);
i++) {
values
result = result * x;
}
x = result; But, what if the
}
argument is the
{ address of a
float p=2.0;
pow_assign(p, 5); variable?
}
float 2.0
32.0
x
uint32 5
_t exp
float 2.0 Grows
float 1.0
32.0
p
result
21
Passing Addresses
Symb Ad Value
Recall our model for ol dr
variables stored in memory
0
1
What if we had a way to
find out the address of a 2
symbol, and a way to
3
reference that memory
location by address? char x 4 ‘H’
(72)
address_of(y)
== 5
memory_at[5]
char y 5 ‘e’
== 101
(101)
void f(address_of_char p)
{
memory_at[p] = 6
memory_at[p] - 32;
} 7
char y = 101; /* y is 8
101 */
f(address_of(y)); /* i.e.
f(5) */
9
/* y is now 101-32 = 69 */
10
11
22
“Pointers”
23
Pointer Validity
char * get_pointer()
{
char x=0;
return &x;
}
{
char * ptr =
get_pointer();
*ptr = 12; /* valid? */
}
24
Answer: Invalid!
char * get_pointer()
{
char x=0;
return &x;
}
But now, ptr points
{
char * ptr = to a location that’s no
get_pointer();
*ptr = 12; /* valid? */
longer in use, and will
other_function(); be reused the next
}
time a function is
called!
Return
1 int x
char 0
12
456
101
0 average 603 Grows
1
1 char * 101
?
0 ptr
0
25
More on Types
26
Structures
Packin
struct: a way to compose existing types into a g?
structure
27
Arrays
x is
an array
of
pointers Arrays are the
int to
primary source of
int
*x[10]; confusion. When in
x is doubt, use extra
int parens to clarify the
a pointer
(*x)[10]; to expression.
an array
of
int
29
Function Types
For more
The other confusing form is the function type. details:
$ man qsort
For example, qsort: (a sort function in the standard
library)
void qsort(void *base, size_t nmemb, size_t size,
The last
int (*compar)(const void *, const void
*)); argument is a
comparison
/* function matching this type: */ function
int cmp_function(const void *x, const void *y);
const means the
/* typedef defining this type: */ function is not
typedef int (*cmp_type) (const void *, const void
*); allowed to modify
memory via this
/* rewrite qsort prototype using our typedef */
pointer.
void qsort(void *base, size_t nmemb, size_t size,
cmp_type compar);
size_t is an
unsigned int
30
Dynamic Memory Allocation
31
Caveats with Dynamic Memory
32
Some Common Errors and Hints
malloc()
/* allocating a struct with malloc() */ allocates
struct my_struct *s = NULL; n bytes
s = (struct my_struct *)malloc(sizeof(*s)); /*
NOT sizeof(s)!! */ Wh
if (s == NULL) { y?
printf(stderr, “no memory!”);
Always check for NULL.. Even if you
exit(1);
} just exit(1).
33
Macros
34
Macros and Readability
35
Using “goto”
goto try_again;
goto fail;
36
Unrolling a Failed Initialization using goto
state_t *initialize()
{
/* allocate state struct */ state_t *initialize()
state_t *s = {
g_new0(state_t, 1); /* allocate state struct */
if (s) { state_t *s =
/* allocate sub-structure g_new0(state_t, 1);
*/ if (s == NULL) goto free0;
s->sub = g_new0(sub_t,
1); /* allocate sub-structure
if (s->sub) { */
/* open file */ s->sub = g_new0(sub_t, 1);
s->sub->fd = if (s->sub == NULL) goto
open(“/dev/null”, free1;
O_RDONLY);
if (s->sub->fd >= 0) { /* open file */
/* success! */ s->sub->fd =
} open(“/dev/null”,
else { O_RDONLY);
free(s->sub); if (s->sub->fd < 0) goto
free(s); free2;
s = NULL;
} /* success! */
} return s;
else {
/* failed! */ free2:
free(s); free(s->sub);
s = NULL; free1:
} free(s);
} free0:
return s; return NULL;
} }
37
High Level Question: Why is Software
Hard?
Answer(s):
• Complexity: Every conditional (“if”) doubles
number of paths through your code, every bit
of state doubles possible states
– Solution: reuse code paths, avoid duplicate
state variables
38
Addressing Complexity
On receive_packet:
if queue full, drop packet
else push packet, call
run_queue On input, change our state as
needed, and call Run_queue. In
On transmit_complete:
state=idle, call run_queue
all cases, Run_queue handles
taking the next step…
Run_queue:
if state==idle && !queue
empty
pop packet off queue
start transmit, state =
busy
39
Addressing Complexity
Why return -
1?
40
Addressing Mutability
struct pkt_hdr {
int source; struct pkt_hdr {
int dest; int source;
int length; int dest;
}; int length;
Otherwise
struct pkt { }; when one
int source; struct pkt {
int dest; struct pkt_hdr
changes, you
int length; hdr; have to find
uint8_t uint8_t
payload[100]; payload[100];
and fix all the
}; }; other places
41
Solutions to the pow() challenge question
Recursive Iterative
return result;
}
42