530 likes | 682 Views
C Programming. - Structures. Structures containing arrays. A structure member that is an array does not ‘behave’ like an ordinary array When copying a structure that contains a member which is an array, the array is copied element by element Not just the address gets copied
E N D
C Programming - Structures
Structures containing arrays • A structure member that is an array does not ‘behave’ like an ordinary array • When copying a structure that contains a member which is an array, the array is copied element by element • Not just the address gets copied • For example - array_member.c • Reminder – ordinary arrays can’t be copied simply by using the ‘=‘ operator • They must be copied using a loop
Structures containing arrays • When passing the structure to a function by value • Changing the array field inside the function won’t change it in the calling function • Reminder – when passing an ordinary array to a function, all that gets passed is the address of its first element • Hence every change to the array within the function, changes the array in the calling function
C Programming Pointers
Pointers • A new type of variable • Its value is the address of another variable • We declare a pointer variable by adding a ‘*’ before the variable name: type *variable_name;
Name i p q j int* Type int int int* 2004 2000 2012 address 2008 2000 2000 value 5 10 address of i Understanding Pointers int i = 5; int j = 10; int* p = &i; int* q = p; j = *p; The value of q equals the value of p • Evaluate the right hand side of the assignment: • Go to the variable pointed by p andtake its value
Referencing • The unary operator & gives the address of a variable • The statement: ptr = &c; assigns the address of c to the pointer variable ptr, and now ptr points to c
Referencing - Example int n; int *iptr; /* Declare iptr as a pointer to int */ n = 7; iptr = &n; n … 7 3 4 … 172 173 174 175 176 177 178 179 180 181 iptr … 174 3 4 … 832 833 834 835 836 837 838 839 840 841
Dereferencing • The unary operator * is the dereferencing operator • Applied ONLY on pointers • Access the object the pointer points to • The statement: *iptr = 5; puts 5 in the variable pointed by iptr
Dereferencing printf(“%d”, *iptr); /* Prints out ‘7’ */ *iptr = 181; printf(“%d”, n); /* Prints out ‘181’ */ iptr = 181; /* This is unadvisable!! */ n 181 7 … 3 4 … 172 173 174 175 176 177 178 179 180 181 iptr 181 174 … 3 4 … 832 833 834 835 836 837 838 839 840 841
Pointers Example x y int x=1, y=2, z[3]={5,6,7}; int *ip; ip = &x; y = *ip; *ip = 0; ip = z; ip = &z[2]; *ip = 1; 1 2 120 248 Z[0] Z[1] Z[2] 5 6 7 364 368 372 z ip 364 … 564 772
Pointers Example x y int x=1, y=2, z[3]={5,6,7}; int *ip; ip = &x; y = *ip; *ip = 0; ip = z; ip = &z[2]; *ip = 1; 1 2 120 248 Z[0] Z[1] Z[2] 5 6 7 364 368 372 z ip 364 120 564 772
Pointers Example x y int x=1, y=2, z[3]={5,6,7}; int *ip; ip = &x; y = *ip; *ip = 0; ip = z; ip = &z[2]; *ip = 1; 1 1 120 248 Z[0] Z[1] Z[2] 5 6 7 364 368 372 z ip 364 120 564 772
Pointers Example x y int x=1, y=2, z[3]={5,6,7}; int *ip; ip = &x; y = *ip; *ip = 0; ip = z; ip = &z[2]; *ip = 1; 0 1 120 248 Z[0] Z[1] Z[2] 5 6 7 364 368 372 z ip 364 120 564 772
Pointers Example x y int x=1, y=2, z[3]={5,6,7}; int *ip; ip = &x; y = *ip; *ip = 0; ip = z; ip = &z[2]; *ip = 1; 0 1 120 248 Z[0] Z[1] Z[2] 5 6 7 364 368 372 z ip 364 364 564 772
Pointers Example x y int x=1, y=2, z[3]={5,6,7}; int *ip; ip = &x; y = *ip; *ip = 0; ip = z; ip = &z[2]; *ip = 1; 0 1 120 248 Z[0] Z[1] Z[2] 5 6 7 364 368 372 z ip 364 372 564 772
Pointers Example x y int x=1, y=2, z[3]={5,6,7}; int *ip; ip = &x; y = *ip; *ip = 0; ip = z; ip = &z[2]; *ip = 1; 0 1 120 248 Z[0] Z[1] Z[2] 5 6 1 364 368 372 z ip 364 372 564 772
Common errors • It is an error to define pointers to constants or expressions. • i = &3 • j = &(k + 5) • It is an error to change a variable’s address (because it is not for us to determine!). • &a = 150 • &a = &b • Dereferencing un-initialized pointers int* a;...*a = 5;
What will be printed? int main() { int a=3,b=6,c; int *x=&a; printf(“c=%d\n”,c); } c=b*(*x); c=b**x;
Function Arguments • Functions receive their arguments “by value” • Cannot change the value in the caller void increment_counter(int counter){ counter++;}
Pointers as Function Arguments • If we want to change a variable in the function we can pass its address – a pointer! • Call “by reference” void increment_counter(int* counter){ (*counter)++;}
Caller Callee by value mainincerement_counter(X) mainincerement_counter(&X) increment_counter(int counter) X copy of X by reference increment_counter(int* counter) counter
Wrong Swap • A swap that gets integers as variables does not change the value in the original variables. void swap(int x, int y) { int tmp = x; x = y; y = tmp; }
How can we fix it? • We can define swap so it gets pointers to integers instead of integers void swap(int *x, int *y) { …swap *x and *y… } • We then call swap by swap(&x, &y); • This is passing values by address
Right Swap – add_swap.c void swap(int *x, int *y) { int tmp = *x; *x = *y; *y = tmp; }
Back to scanf • 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* int_part, double* frac_part) • The function accepts a double parameter and returns its integer and fraction parts. • Write a program that accepts a number from the user and prints out its integer and fraction parts.
Solution void split(double num, int *int_part, double *frac_part) { *int_part = (int)num; *frac_part = num - *int_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; }
Pointers and Arrays • An array is consecutive bytes in memory • The name of the array is the address of the first element.arr is the address of arr[0] • Unlike pointers this address cannot be changed
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; same as arr[0] = 6
Pointer arithmetic • Pointers can be incremented and decremented • If p is a pointer to a particular type, p+1 yields the correct address of the next variable of the same type • p++,p+i, and p += i also make sense
Pointer arithmetic • If p and q point to elements in an array, q-p yields the number of elements between p and q. • You can’t add two pointers • There is a difference between pointer arithmetic and “regular” arithmetic.
Pointer arithmetic - example int main(void) { int a[3] = {17,289,4913}, *p, *q; p = a; /* p points to the beginning of a, that is &a[0] */ q = p+2; /* q points to a[2]. Equivalent to q = &a[2] */ printf(“a is %p\n", a); printf("p is %p, q is %p\n", p, q); printf("p points to %d and q points to %d\n", *p, *q); printf("The pointer distance between p and q is %d\n", q-p); printf("The integer distance between p and q is %d\n", (int)q-(int)p); return 0; } a is 0012FECC p is 0012FECC, q is 0012FED4 p points to 17 and q points to 4913 The pointer distance between p and q is 2 The integer distance between p and q is 8
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘!’ ‘!’ ‘!’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘!’ ‘!’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘!’ ‘!’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘!’ ‘!’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘!’ ‘!’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘e’ ‘!’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘e’ ‘!’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘e’ ‘!’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘e’ ‘!’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘e’ ‘s’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘e’ ‘s’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘e’ ‘s’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘e’ ‘s’ ‘!’ ‘!’ dest
Strcpy – step by step void my_strcpy(char *dest, char *src) { while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; } ‘y’ ‘e’ ‘s’ ‘\0’ ‘%’ src ‘y’ ‘e’ ‘s’ ‘\0’ ‘!’ dest
Pointers, Arrays and Function Arguments • Consider the following function prototypes • These are all identical void foo(char str[10]); void foo(char str[]); void foo(char* str);
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) { while (*str != '\0') { if (*str == c1) *str = c2; ++str; } }