Programming Pointers
Variables in Memory x i c The compiler determines where variables are placed in memory This placement cannot be changed by the programmer int n; char c; double x;
Address of Operator The operator & gives the address of a variable in memory &i is 1000 &c is 1004 &x is i c x i c
Address of Operator Can only be applied to variables in memory Cannot be applied to expressions and constants &3 &(x + 1) &(a == b)
Address Variables (Take 1) An address is just a number let’s use an integer to hold it int address_n = &n, address_c = &c, address_x = &x; Problem?
Value Given Address The * operator access the content of a variable given its address *address_n gives the value of the variable n How can we tell how many bytes we need to read given an address? We need both the variable’s address and its size
Address Variables (Take 2) Pointers are variables that hold the address of other variables. starting address type (size) i c i c ip cp
A pointer is declared by adding a * before the variable name. double *dp; int *ip, n; char* cp1, *cp2; type* variable_name; Declaring a Pointer Variable pointer to double pointer to int “regular” int pointer to charanother pointer to char
Referencing The operator & gives the address of a variable ptr = &c; Assigns the address of c to the pointer ptr We say that ptr points to c
Dereferencing The operator * is the dereferencing operator Access the variable the pointer points to int n = 1, m = 2; int* ip; ip = &n; m = *ip; *ip = 0; ip is a pointer to int ip now points to x ip now points to n m is now 1 n is now 0
Is This OK? int ival = 1024, ival2 = 2048; int* pi1 = &ival, *pi2 = &ival2; ival = pi2; int int * warning C4047: '=' : 'int' differs in levels of indirection from 'int *'
Is This OK? int ival = 1024, ival2 = 2048; int* pi1 = &ival, *pi2 = &ival2; pi2 = *pi1; int * int warning C4047: '=' : 'int *' differs in levels of indirection from 'int'
Is This OK? int ival = 1024, ival2 = 2048; int* pi1 = &ival, *pi2 = &ival2; ival = *pi1; int ✓
Is This OK? int ival = 1024, ival2 = 2048; int* pi1 = &ival, *pi2 = &ival2; pi1 = ival; int * int warning C4047: '=' : 'int *' differs in levels of indirection from 'int'
NULL Special “address” indicating “nowhere” int* ip = NULL; ip does not point to any variable We can test if (ip != NULL) { *ip = …; }
Function Arguments - Reminder Changes to the local variable do not modify the value in the caller Call “by value” void increment_counter(int counter) { counter++; } int main(void) { int count;... increment_counter(count); }
We can access the variable pointed to by the local variable Call “by reference” Pointers as Function Arguments void increment_counter(int* counter) { (*counter)++; } int main(void) { int count;... increment_counter(&count); }
main incerement_counter(&count) CallerCallee main incerement_counter(count) count by value increment_counter(int counter) by reference increment_counter(int* counter) copy of count counter Pointers as Function Arguments
scanf Revisited We can now understand the & in scanf("%d", &a); The argument list in scanf is simply passed by address, so scanf can change its content
Exercise Implement the function: void split(double d, int* i_part, double* f_part); The function accepts a double parameter and assigns its integer and fraction parts to the two variable pointed to by i_part and f_part respectively. Write a program that accepts a number from the user and prints out its integer and fraction parts.
Solution void split(double d, int* i_part, double* f_part) { *i_part = (int)d; *f_part = d – (*i_part); } int main(void) { double num, fraction; int integer; printf("Please enter a real number: "); scanf("%lf", &num); split(num, &integer, &fraction); printf("The integer part is %d\n", integer); printf("The remaining fraction is %g\n", fraction); return 0; }
Example - Swap void swap(int* x, int* y) { int temp = *x; *x = *y; *y = temp; } Call swap: swap(&x, &y);
Const Pointers A pointer can be declared constant const int* cip; The pointer can be changed, but the object it points to can not. cip = &i; ✓ cip = &j; ✓ *cip = 5; ✗
Pointers as Return Values A function may return the address of a variable The variable must not be a local variable char* strchr(const char* str, char c) { while (*str != '\0') { if (*str == c) return str; ++str; } return NULL; }
Address, Pointers and Arrays int a[10]; Defines a block of 10 consecutive objects named a[0],a[1],…,a[9]. The name of the array is a synonym for the location of the first element. a is &a[0] The name of the array is not a variable, hence its value cannot be modified. a[0] a[1]a[9] a:
Address, Pointers and Arrays a[0] a[1]a[9] a: int a[10]; int *pa; pa: int a[10]; int* pa; pa = &a[0];
Array Names are Not Pointers Pointers are variables (can be modified) legal: pa = a pa++ Array name is not a variable (cannot be modified) illegal: a = pa a++
Pointers Vs. Arrays - Example int arr[3] = {1, 2, 3}; int* ptr; const int* cptr; arr = ptr; ptr = arr; *ptr = 3; cptr = arr; *cptr = 5; ptr = cptr; *arr = 6;
Pointer Arithmetic If pa points to an element in the array, then pa+1 points to the next element pa+i points I elements after pa a[0] a[1]a[9] a: pa: pa+1: pa+2:
Pointer Arithmetic if pa points to a[0] *(pa + 1) is the content of a[1] *(pa + i) is equivalent to a[i]
More Pointer Arithmetic Pointers can be incremented and decremented p++ advance p one place in the array p += I advances p i places in the array Example: if str points to the first character of a string then str + strlen(str) -1 points to the last character
Pointers and Increment Operators Walk down an array Pointer notation ++(*p) - increment thing pointed to (*p)++ - increment thing pointed to *(p++) - fetch value, then increment pointer *(++p) - increment pointer, then fetch value int ar[ARLEN], *ip; ip = ar; while(ip < &ar[ARLEN]) *(ip++) = 0;
Reverse int main(void) { char str[STR_SIZE + 1]; char* ptr = NULL; printf("Enter a string:\n"); getline(str, STR_SIZE); for (ptr = str + strlen(str) - 1; ptr >= str; --ptr) { putchar(*ptr); } putchar('\n'); return 0; } \0 str: ptr:
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’‘e’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’‘e’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’‘e’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’‘e’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’‘e’‘s’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’‘e’‘s’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’‘e’‘s’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’‘e’‘s’ dest...
my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’‘e’‘s’‘\0’ src ‘y’‘e’‘s’‘\0’ dest...
Using my_strcpy int main(void) { char str[STR_LEN + 1], temp[SR_LEN + 1];... my_strcpy(temp, str);... }
Common Error Return of a local array char* foo(const char* str) { char temp[BIG_ENOUGH]; strcpy(temp, str); /* manipulate temp */... return temp; }
Exercise Write a function with the prototype: void replace_char(char* str, char c1, char c2); It replaces each appearance of c1 by c2 in the string str. Do not use the [] operator! Demonstrate your function with a program that uses it
Solution void replace_char(char* str, char c1, char c2) { if (str == NULL) return; while (*str != '\0') { if (*str == c1) *str = c2; ++str; }