Week 5 9 April 2018 NWEN 241 More on pointers Alvin Valera School of Engineering and Computer Science Victoria University of Wellington
Admin stuf Exercises (Set 3): Covers Weeks 4-5 lessons Download from NWEN 241 course wiki Solutions will be released on Friday (13 Apr 2018) Some of the questions will be discussed in Tutorial NWEN 241: Systems Programming 2
Admin stuf Clarifications on Programming Assignment 2: How to deal with a user input that is already taken You can either (a) skip player and go to the other player, or (b) force the player to enter an untaken box Important thing is your program should handle them consistently and not crash when such exceptions occur How to deal with a user input that is out of bounds or invalid Force the player to enter a value that is within bounds. If user enters value that is already taken, then apply (a) or (b) NWEN 241: Systems Programming 3
Recap: pointer basics A pointer is a variable that contains memory address A pointer points to a memory location To obtain value of data pointed to by pointer, need to perform indirection or dereferencing NWEN241 Systems Programming 4
Recap: pointer-related operators Address operator (&) The operation will return the memory location of the variable Can be applied on any variable, including pointers Indirection operator (*) The operation will return the value of data pointed to by pointer Can only be applied on pointer variables NWEN241 Systems Programming 5
Recap: pointer arithmetic Addition and subtraction can be performed on pointer variables Result depends on data type pointed to by pointer Suppose : data_type *name; name + k name - k Evaluated as name + k*sizeof(data_type) Evaluated as name - k*sizeof(data_type) NWEN241 Systems Programming 6
Recap: Usage of pointers 1) Provide an alternative means of accessing information stored in arrays 2) Provide an alternative (and more eficient) means of passing parameters to functions 3) Enable dynamic data structures, that are built up from blocks of memory allocated from the heap at run time NWEN241 Systems Programming 7
Traversing arrays using pointers The usual way to iterate over arrays: int a[] = {... ; int len = sizeof(a)/sizeof(int); for(int i = 0; i < len; i++) { /* Do something about a[i] */ Using pointers: int a[] = {... ; int len = sizeof(a)/sizeof(int); for(int *ip = a; ip < a + len; ip++) { /* Do something about *ip */ NWEN241 Systems Programming 8
Traversing arrays using pointers int a[] = {... ; int len = sizeof(a)/sizeof(int); for(int *ip = a; ip < a + len; ip++) { /* Do something about *ip */ 1 st iteration: a... ip NWEN241 Systems Programming 9
Traversing arrays using pointers int a[] = {... ; int len = sizeof(a)/sizeof(int); for(int *ip = a; ip < a + len; ip++) { /* Do something about *ip */ 2 nd iteration: a... ip NWEN241 Systems Programming 10
Traversing arrays using pointers int a[] = {... ; int len = sizeof(a)/sizeof(int); for(int *ip = a; ip < a + len; ip++) { /* Do something about *ip */ 3 rd iteration: a... ip NWEN241 Systems Programming 11
Traversing arrays using pointers int a[] = {... ; int len = sizeof(a)/sizeof(int); for(int *ip = a; ip < a + len; ip++) { /* Do something about *ip */ (len-1)th iteration: a... ip NWEN241 Systems Programming 12
A note on operator precedence Previously, operator precedence table from Kernighan & Ritchie: NWEN241 Systems Programming 13
A note on operator precedence Slight correction: These only refer to prefix ++ and -- Postfix ++ and has level 1 precedence, i.e., the same as (), [], -> and. NWEN241 Systems Programming 14
Increment and indirection together Suppose int *ip; int i; What does i = *ip++ mean? Since ++ has higher precedence than *, the RHS expression evaluates to *(ip++) which means i = *ip; ip = ip + 1; NWEN241 Systems Programming 15
Increment and indirection together Suppose int *ip; int i; What does i = *++ip mean? Both ++ and * have same precedence, so associativity is applied on RHS yielding *(++ip) which means ip = ip + 1; i = *ip; NWEN241 Systems Programming 16
Increment and indirection together Suppose int *ip; int i; How to increment the value of whatever ip points to? (*ip)++; NWEN241 Systems Programming 17
Strings Pointers int strlen (char *s) { int n; for(n=0; *s!='\0'; s++) n++; return n; Notice in the second strcmp() and second and third strcpy(), the use of pointers to iterate through the strings 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]; int strcmp(char *s, char *t) { for(;*s == *t; s++,t++) if (*s == '\0') return 0; return *s - *t; void strcpy(char *s, char *t) { int i = 0; while((s[i]=t[i])!= '\0') i++; void strcpy(char *s, char *t) { while((*s=*t)!= '\0') { s++; t++; void strcpy(char *s, char *t) { while((*s++=*t++)!= '\0'); The conciseness of the last strcmp() and strcpy() make them hard to understand NWEN241 Systems Programming 18
A closer look at strcmp() int strcmp(char *s, char *t) { for(;*s == *t; s++,t++) if (*s == '\0') return 0; return *s - *t; What is the meaning of the return value? If strings are the same, return value is 0 If strings are not the same, return value is *s - *t Return value indicates lexicographical order of s and t: Positive if s appears afer t, negative otherwise NWEN241 Systems Programming 19
Reference / variable parameters To make changes to a variable that exist afer a function ends, we pass the address of the variable to the function (a reference parameter) Then we use indirection operator inside the function to change the value the parameter points to: int a, b; swap(&a, &b); void swap(int *px, int *py) { int tmp; tmp = *px; *px = *py; // values stored at *py = tmp; // addresses of 'a' // and 'b' are swapped NWEN241 Systems Programming 20
Returning pointers from functions A function can also return a pointer value: float *find_max(float A[], int N) { int i; float *the_max = &(A[0]); for (i = 1; i < N; i++) if (A[i] > *the_max) the_max = &(A[i]); return the_max; int main(void) { float scores[5] = {10.0, 8.0, 5.5, 2.0, 4.1; float *max_score; max_score = find_max(scores, 5); printf("%.1f\n",*max_score); return 0; NWEN241 Systems Programming 21
Returning pointers from functions Caution!!! In functions, do not do return p, where p is a pointer to a local variable. This is because local variables are de-allocated when the function ends so whatever p is pointing to will no longer be available but if you return the pointer, then you still are pointing at that memory location even though you no longer know what is there Question: Why is it allowed in the previous example? NWEN241 Systems Programming 22
Pointer to pointers A pointer can also be made to point to a pointer variable (but the pointer must be of a type that allows it to point to a pointer) Example: int V = 101; int *P = &V; /* P points to int V */ int **Q = &P; /* Q points to int pointer P */ printf("%d %d %d\n", V, *P, **Q); /* prints 101 3 times */ NWEN241 Systems Programming 23
Pointer arithmetic Assume short is 2 bytes, and pointer variable (address size) is 4 bytes. short a[10]={5, 10, 15, ; short *pa, **ppa; int i=5; pa = &a; ppa = &pa; ppa 800 700 700 pa 640 Variable Address Value a 640 5 642 10 644 15 640 642 644 646 648 650 a 5 10 15 pa 700 640 ppa 700 700 Questions: Expression Value Note pa+1 642 640+1*2 pa+3 646 640+3*2 pa+i 650 640+i*2 *pa+1 6 5+1 *(pa+1) 10 a[1]=pa[1]=*(a+1) pa[2] 15 644 *ppa 640 Value of pa *ppa+1 642 pa+1 *(*ppa+1) 10 *(pa+1) *(ppa+1) invalid *(704) NWEN241 Systems Programming 24
Pointer types Pointers are generally of the same size, but it is inappropriate to assign an address of one type of variable to a diferent type of pointer Example: int V = 101; float *P = &V; /* generally results in a warning */ Warning rather than error because C will allow you to do this (it is appropriate in certain situations) NWEN241 Systems Programming 25
Casting pointers When assigning a memory address of a variable of one type to a pointer that points to another type, it is best to use the cast operator to indicate the cast is intentional (this will remove the warning). Example: int V = 101; float *P = (float *) &V; /* Casts int address to float * */ Removes warning, but is still unsafe to do this!!! NWEN241 Systems Programming 26
General (void) pointer A void * is considered to be a general pointer No cast is needed to assign an address to a void * or from a void * to another pointer type Example: int V = 101; void *G = &V; /* No warning */ float *P = G; /* No warning, still unsafe */ Certain library functions return void * results NWEN241 Systems Programming 27
Pointers and const Const pointer: cannot be reassigned to point to a diferent location from the one it is initially assigned, but it can be used to modify the location that it points to data_type * const p; Pointer to a const location: can be reassigned to point to a diferent location, but it cannot be used to modify any location that it points to const data_type * p; Const pointer to a const location: can neither be reassigned nor used to modify the location that it points to const data_type * const p; NWEN241 Systems Programming 28
Pointer to function Function code is stored in memory Functions also occupy memory locations therefore every function has an address just like variables Just like ordinary variables, the address of a function refers to its starting address C does not require that pointers only point to data, it is possible to have pointers to functions NWEN241 Systems Programming 29
Defining a function pointer Declaration: return_type (*name)(param_types); Examples int (*f)(int, float); int *(*f)(int, float); Pointer to a function that takes an int and float arguments, resp., and returns an int Pointer to a function that takes an int and float arguments, resp., and returns a pointer to int NWEN241 Systems Programming 30
Using a function pointer /* f is a function pointer */ int (*fp)(int, float); int F1(int i, float f) { return i/f; int main(void) { /* Assignment: let f point to F1 */ fp = &F1; /* fp = F1; is also ok */ /* Invocation */ float a = fp(1, 2.0); /* This is equivalent to calling F1(1, 2.0) */ NWEN241 Systems Programming 31
Comparing function pointers Can use the equality (==) operator Example: /* f is a function pointer */ int (*fp)(int, float); int F1(int i, float f) { return i/f; int main(void) { /* Assignment: let f point to F1 */ fp = &F1; /* fp = F1; is also ok */ if(fp == &F1) printf("points to F1\n"); NWEN241 Systems Programming 32
Safety concerns What if uninitialized function pointer value is accessed Safest outcome: memory error, and program is terminated But what if the garbage value is a valid address? Worst case: address contains program instruction execution continues, with random results Hard to trace the cause of the erroneous behavior NWEN241 Systems Programming 33
Usage of function pointers For implementing callback functions Function pointer is passed as an argument to a function The function will then invoke the passed function pointer at a given time void qsort(void *base, size_t nitems, size_t size, int (*compare)(const void *, const void*)); base Pointer to the first element of the array to be sorted nitems Number of elements in the array pointed by base size Size in bytes of each element in the array. compare This is the function that compares two elements. NWEN241 Systems Programming 34
Next lecture Storage classes NWEN241 Systems Programming 35