Pointers
A pointer in C holds the memory address of a value
the value of a pointer is an address
the value of the memory location pointed at can be obtained by
address)
memory location address
p
129 10000
pointer 10004 77 10001
31542 10002
dereferencing:
108 10003
*
97 10004
542 10005
100652 10006
1
C pointers
a pointer is the address of a memory location
no explicit type information associated with it
arithmetic on pointers is allowed, e.g.:
*(p+27)
2
Declaring pointer variables
Two new operators (unary, prefix):
&
*
Declarations:
a pointer x to something of type T is declared as
T *x
Example: int *p; // p: pointer to an int
char **w; // w: pointer to a pointer to a char
Using pointer-related operators
If x is a variable, &x is the address of x
If p is a pointer, *p is the value of whatever points to
*(&p) p always
4
Arrays
An array in C is just a contiguous sequence of
memory locations
size of each element depends on type
the length of the array is not part of the array type
the language does not require that array accesses be
checked to be within the array bounds
out-of-
More arrays
Consider an array declared as:
int A[20];
the value of A[i] is the contents of the memory location
occupied by element i of A;
the value of A is the address of the array A, i.e., &(A[0]);
this does not have size information associated with it.
6
More arrays
To pass an array as an argument to a function, you
pass the array name
since the value of the array name is the address of the
array, what is actually passed is a pointer to the array
This does not have size information associated
the called function does not know how big the array is
need to provide a mechanism for callee to figure this out:
either pass the size of the array separately; or
terminate the array with a known value (e.g., 0)
scanf() and pointers
To read input using scanf(), we have to provide:
a format string with conversion specifications (%d, %s, etc.)
that says what kind of value is being read in; and
a pointer to (i.e., the address of) a memory area where the
value is to be placed
Reading in an integer:
int x;
// &x address of x
Reading in a string:
// str address of the array str
8
*p++ vs. (*p)++
x
p
after x = *p++ after x = (*p)++
x x
p p
Two common pointer problems
Uninitialized pointers
the pointer has not been initialized to point to a valid
location
Dangling pointers
the pointer points at a memory location that has actually
been deallocated
10
Background: Runtime Memory Organization
0xffffffff high addresses
operating system
stack
(grows downwards)
memory mapped files
heap
(grows upwards)
global data
code low addresses
0x00000000
11
Background: Runtime Memory Organization
Code: Runtime stack:
stack growth
}
top of
stack
}
}
12
Background: Runtime Memory Organization
Code: Runtime stack:
stack growth
}
top of
stack
}
}
13
Background: Runtime Memory Organization
Code: Runtime stack:
stack growth
}
}
} top of
stack
14
Background: Runtime Memory Organization
Code: Runtime stack:
stack growth
}
}
}
{
top of
stack
}
15
Background: Runtime Memory Organization
Code: Runtime stack:
stack growth
}
}
} top of
stack
stack frame
{ (deallocated)
16
Background: Runtime Memory Organization
Code: Runtime stack:
stack growth
}
top of
stack
} stack frame
stack frame
{
17
Background: Runtime Memory Organization
Code: Runtime stack:
stack growth
}
} stack frame
top of stack frame
{ stack
18
Structs
A struct is
an aggregate data structure, i.e., a collection of other
data;
by contrast, arrays contain components of the same type
fields are accessed by name
by contrast, array elements are accessed by position
Unlike Java classes, a struct can only contain data,
not code.
19
Declaring structs
A node for a linked list struct node
of integers: val
next
struct node {
int val;
struct node *next;
}
used to refer to the
structure
20
Accessing structure fields
Given Given
a struct s containing a a pointer p to a struct s
field f containing a field f
to access f, we write to access f we write
s.f declares x, y to be p->f // eqvt. to: (*p).f
variables of type
Example: struct foo
Example:
struct foo { struct foo {
int count, bar[10];
int count, bar[10];
} *p, *q;
} x, y;
x.count = y.bar[3]; p->count = q->bar[3];
21
Operator Precedence and Associativity
Operator precedence and associativity define how an
expression is parsed and evaluated
The text (King, C Programming: A Modern Approach),
Appendix A has a full list of all C operator precedences
Some highlights: in decreasing order of precedence:
postfix expressions ( [ ] ( ) -> . ++postfix --postfix )
unary expressions ( ++prefix --prefix & * + - ~ ! sizeof )
type cast
arithmetic: multiplicative additive bit-shift
relational (not all of the same precedence)
bitwise operators (not all of the same precedence)
22
Operator Precedence Examples
Decreasing order of How are these parsed?
precedence: *p++ ++ binds tighter than *:
postfix expressions *(p++) not: (*p)++
[ ] ( ) -> . ++post --post
*p->q -> binds tighter than *:
unary expressions *(p->q) not: (*p)->q
++pre --pre & *deref + - ~ ! sizeof
*A[10] [ ] binds tighter than *:
type cast *(A[10]) not: (*A)[10]
arithmetic
*p->q++ -> and ++ left-associative:
*( (p->q) ++ )
23
l-values for structs and pointers
e.name is an l-value iff e is an l-value
e->name is always an l-value, regardless of whether e
is an l-value
*e is always an l-value, regardless of whether e is an
l-value
the operand of an address-of operator & must be an
l-value
the operand of a unary ++ or -- operator (prefix or
postfix) must be an l-value
24