510 likes | 609 Views
Programming. Pointers. Variables in Memory. The compiler determines where variables are placed in memory This placement cannot be changed by the programmer. int n; char c; double x;. x. 1000. 1003. 1004. 1005. 1012. i. c. Address of Operator.
E N D
Programming Pointers
Variables in Memory • The compiler determines where variables are placed in memory • This placement cannot be changed by the programmer int n;char c;double x; x 1000 1003 1004 1005 1012 i c
Address of Operator • The operator & gives the address of a variable in memory • &i is 1000 • &c is 1004 • &x is 1005 x 1000 1003 1004 1005 1012 i i c 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) 1000 1003 1004 i i ip cp 1004 1000 c c
Declaring a Pointer Variable • A pointer is declared by adding a * before the variable name. • double *dp; • int *ip, n; • char* cp1, *cp2; type* variable_name; pointer to double pointer to int “regular” int pointer to char another 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 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 testif (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);}
Pointers as Function Arguments • We can access the variable pointed to by the local variable • Call “by reference” void increment_counter(int* counter){ (*counter)++;}int main(void){int count; ... increment_counter(&count);}
Pointers as Function Arguments Caller Callee by value mainincerement_counter(&count) mainincerement_counter(count) increment_counter(int counter) count copy of count by reference increment_counter(int* counter) counter
scanf Revisited • We can now understand the & inscanf("%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(constchar* str, char c){while (*str != '\0') {if (*str == c)return str; ++str; }return NULL;}
a: a[0] a[1] a[9] 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.
pa: a: a[0] a[1] a[9] Address, Pointers and Arrays int a[10];int *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; constint* cptr; arr = ptr; ptr = arr; *ptr = 3; cptr = arr; *cptr = 5; ptr = cptr; *arr = 6;
pa: a: a[0] a[1] a[9] 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 pa+2: pa+1:
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;
ptr: 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; } str: \0
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char* dest, const char* src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ‘e’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char*dest, const char*src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ‘e’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char*dest, const char*src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ‘e’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char*dest, const char*src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ‘e’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char*dest, const char*src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ‘e’ ‘s’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char*dest, const char*src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ‘e’ ‘s’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char*dest, const char*src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ‘e’ ‘s’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char*dest, const char*src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ‘e’ ‘s’ ...
‘y’ ‘e’ ‘s’ ‘\0’ my_strcpy void my_strcpy(char*dest, const char*src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } src ... dest ‘y’ ‘e’ ‘s’ ‘\0’ ...
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(constchar* 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