Professional Documents
Culture Documents
3101 1 Lec4
3101 1 Lec4
Programming Languages – C
Lecture 4
Matthew P. Johnson
Columbia University
Fall 2003
10/17/08 CS3101-1, Lecture 4 1
Important Reminder
• Do not let me fail to repeat Qs
• Remind me if I forget
– And before I complete the answer
Win valuable prizes
• After execution, x == 0, y == 1
10/17/08 CS3101-1, Lecture 4 9
& and *
• & and * (as ptr ops) are inverses
– Cancel each other out
• Examples
• *&x “the value at the address of x”
x
– Who is buried in Grant’s tomb?
• &*xp “the address of the value at the
address xp” xp
– Where is the contents of Grant’s tomb?
10/17/08 CS3101-1, Lecture 4 10
Pointer declars
• To declar ptr-to-type var, similar to type
declar, plus *:
– int *ip;
• Interp 1: ip is an int-pointer: (int*) ip
• Interp 2: dereferenced ip is an int: int
(*ip)
• Notice: primitives, arrays, ptrs, ftns, can
all be declared together:
– int x, *ip, y, z[10], myftn();
10/17/08 CS3101-1, Lecture 4 11
Dereferenced ptrs
• Dereferenced ptr gives the actual
lvalue, not simply a passive value
• Can be used just as the corresponding
var could be
– Both accessed and modified
– *ip = *ip + 1;
– *, &, other unaries have high precedence
– *ip += 1;
• 0 1 2 3 4 5 6 7 8 9
• a[0] gives an int
• &a[0] gives the address of that int
10/17/08 CS3101-1, Lecture 4 20
Pointers & Arrays
• “Ordinary” ptrs can point to arrays:
• pa = &a[0];
pa: a[0]
a:
0 1 2 3 4 5 6 7 8 9
• Now can get other array elms”
– pa+1 points to next
– pa+2
– pa++
– pa-1 points to prev
10/17/08 CS3101-1, Lecture 4 21
Pointers & Arrays
• Q: How does it know they’re ints?
• A: pa is an int*
– why ptrs need to know referent type
• Turns out: array name evals to ptr to
0th elm
– a == &a[0]
– & not applied array name
10/17/08 CS3101-1, Lecture 4 22
Pointers & Arrays
• Also turns out:
• a[i] (array index notation)
evals to same as
*(a+i) (ptr + offset notation)
• array[index] is really short-cut notation
• array[index] converted to *(array+index) in compilation
• Also, array[index] notation applicable to regular pointers:
– ip[20] *(ip+20) who knows?
– As usual, be careful!
• array[index] converted to *(array+index) in compilation
• Q: What if 2[a]?
• A: 2[a] *(2+a) *(2+a) (by symmetry) a[2]
10/17/08 CS3101-1, Lecture 4 23
Array/ptr example
• Consider a string-length ftn:
• int strlen(char *s) {
int n;
for (n = 0; *s != ‘\0’; s++)
n++;
return n;
}
• Now change to:
• int strlen(char s[]) { … Effects?
10/17/08 • None! CS3101-1, Lecture 4 24
Arrs/ptrs as ftn args
• Can call:
– strlen(“hi”), strlen(a), strlen(pa)
– Local var s set to pt to arg passed
• Same behavior:
– strlen(a+2), strlen(&a[2])
• Initly, p == s ‘H’
• ‘H’ != ‘\0’ p++ /* p-s == 1 */
• ‘i’ != ‘\0’ p++ /* p-s == 2 */
• ‘\0’ == ‘\0’ return 2
10/17/08 CS3101-1, Lecture 4 29
Pointer arithmetic
• Here:
– p-as-number – s-as-number == p-s == 2
• For other elm types:
– p-as-number – s-as-number == (p-
s)*sizeof(type)
• Sizeof gives # in var/type:
– sizeof(int), sizeof(x)
• No effect here since sizeof(char) == 1
• Show sizeof.c
10/17/08 CS3101-1, Lecture 4 30
String literals
• “Hi” {‘H’, ‘i’, ‘\0’}
• len-n str literal is a len-n+1 char[]
– Signal ‘\0’ indicates the end
• Same effect:
– char am[] = “hi”; /* am is immutable */
– char am[] = {‘H’, ‘i’, ‘\0’};
• Slightly different effect:
– char *pm = “hi”; /* pm is mutable */
• pm: am[0]
• am:
10/17/08
0 1 2 CS3101-1,
3 4Lecture
54 6 7 8 9 31
Copying strings
• How to copy strings?
• s = t;?
• No: simply makes s and t pt to same chars
• Want: copy actual chars, so indy, from source t to dest s
• For now: assume s pts to enough free space
• Copy strings as arrays:
• void strcpy(char s[], char t[]) {
int i = 0;
while ((s[i] = t[i]) != ‘\0’)
i++;
}
• Each time around, 1) Assign s char to t char; 2) check for \0
• NB: Assign expr evals to char assigned
10/17/08 CS3101-1, Lecture 4 32
Copying strings’
• Copy strings as pointers:
• void strcpy(char *s, char *t) {
while ((*s = *t) != ‘\0’) {
s++;
t++;
}
}
• Essentially the same as prev
• No index needed, but now inc both ptrs
10/17/08 CS3101-1, Lecture 4 33
Copying strings’’
• Mix & match:
• void strcpy(char s[], char *t) {
/* s arr, t ptr */
int i = 0;
while ((*s = t[i]) != ‘\0’) {
s++; /* s ptr */
i++; /* t arr */
}
}
10/17/08 CS3101-1, Lecture 4 34
Copying strings’’’
• Shorter version:
• void strcpy(char *s, char *t) {
while ((*s++ = *t++) != ‘\0’)
;
}
• Each time around: *s set to *t, check for ‘\0’
• But: unaries assoc R-to-L
• So, Q: why do we get *t instead of *(t+1)
• A: in *t++, ++ is eval-ed before *
– But postfix ++ *lval++ evals to simply lval
– After eval, lval is inc-ed
– So *s set to *t; both inc-ed
10/17/08 CS3101-1, Lecture 4 35
Copying strings’’’’
• Q: What is the value of the null char ‘\0’?
• A: 0; any other char is != 0
• Can take advantage of this in if
• Shortest (?) version:
• void strcpy(char *s, char *t) {
while ((*s++ = *t++))
;
}
• Real strcpy lives in string.h
10/17/08 CS3101-1, Lecture 4 36
Comparing strings
• Return <0 if s < t, 0 if s==t, >0 o.w.
• int strcmp(char *s, char *t) {
int i;
for (i = 0; s[i] == t[i]; i++)
if (s[i] == ‘\0’)
return 0;
return s[i] – t[i];
}
• NB: two poss outcomes:
– Get through all of s w/o discrepancy 0
– Find discrepancy amt greater s[i] than t[i]
10/17/08 CS3101-1, Lecture 4 37
Comparing strings’
• With arrays:
• int strcmp(char *s, char *t) {
for(; *s == *t; s++, t++)
if (*s == ‘\0’)
return 0;
return *s - *t;
}
• Omits i but needs , to combine inc stmts
10/17/08
– Very rarely CS3101-1,
used Lecture 4 38
*/++/-- and stacks
• Lend themselves to elegant stack pushing
and popping:
– p points to 1 place above top of stack
– pal is value pushed/popped
• Push: *p++ = val;
– *(p++) evals to *p, so val is written to open slot
– then p is inc-ed
• Pop: val = *--p;
– *(--p) evals to p-1, the last written slot
– Val in last written slot is stored in val
– Last written slot now considered open, for pushing
10/17/08 CS3101-1, Lecture 4 39
Arrays of ptrs/ptrs to ptrs
• Consider problem of sorting, say, ints
• int a[] = {5,23,8,22,99,53,3,77,4,7};
• a: 5 23 8 22 99 53 3 77 4 7
• If sort, get:
• a: 3 4 5 7 8 22 23 53 77 99
• Q: How much work?
• A: W/good alg, O(n*logn) int swaps/compars
– Read/write 4*O(n*logn) bytes
10/17/08 CS3101-1, Lecture 4 40
Arrays of ptrs/ptrs to ptrs
• a: 5 23 8 22 99 53 3 77 4 7
• What if the nums are the values being
sorted, but just they’re keys
• Q: What if we’re sorting records, or
mp3s? How much work then?
• Q: O(n*logn) mp3 swaps/compars!
– Read/write sizeof(mp3)*O(n*logn) bytes
– A lot more work!
10/17/08 CS3101-1, Lecture 4 41
Arrays of ptrs/ptrs to ptrs
• What to do?
• Soln: in general, don’t sort vals;
– Sort pointers (to vals)
– Values stay put
– Only arrows move
• Q: How much work is this?
• A: O(n*logn) ptr swaps/compars!
– Read/write sizeof(ptr)*O(n*logn) bytes
– Q: How large is a ptr?
– A: It’s just a memory addres
• i.e., the integer that refers to some mem location
• 4 bytes, say
– Same as sorting ins
– A lot less work!
• See qsort, which takes an array of ptrs to be sorted
10/17/08 CS3101-1, Lecture 4 42
Array review
• Arrays are complex (=non-
primitive) data structures
• Ordered, fixed-length seq of vars
• All elms same type
• Access by index: ar[4]
• Indices begin at 0
10/17/08 CS3101-1, Lecture 4 43
qsort
• Header (simplified, from stdlib.h):
• void qsort(void *base, int n, int size, int
(*cmp)(const void *, void *));
• Params:
– base ~ ptr to beginning of array
– n ~ array length (= # elements)
– size ~ arr elm size, i.e., “sizeof(base[0])”
– cmp ~ comparison ftn to be used for sort
10/17/08 CS3101-1, Lecture 4 44
qsort’s cmp
• Comparison ftn ops on 2 elm of array:
– cmp(a,b) <0 “a < b”
– cmp(a,b)==0 “a == b”
– cmp(a,b) >0 “a > b”
• Remember (from 3203/intution): alg for
deciding less/=/greater for any 2 elms of set ~
ordering of set
• cmp is used as </==/> would be if sorting ints
• Only complication: cmp takes ptrs, so must *
10/17/08 CS3101-1, Lecture 4 45
Example cmp
• Simple case: int *’s More succinct?
• int cmp(int *a, int int cmp(int *a, int *b) {
*b) { return *a - *b;
if (*a == *b) }
return 0; For other types, modify compars
if (*a < *b)
return -1;
return +1;
}