260 likes | 276 Views
Learn about pointers in C programming, including call by reference, efficient memory allocation, pointer arithmetic, passing arrays to functions, string manipulation, dynamic memory allocation, multidimensional arrays, and functions as arguments. Includes example code and explanations.
E N D
Pointers Chapters 6+9 in ABC
Pointers • int a = 1, b = 2, *p; • & - reference operator (address) • * - dereference operator (value) • p = &a; // *p is now 1
Why are they important? • Call by reference • Efficient argument passing to functions • Dynamic memory allocation • Efficient memory manipulation
Call by reference Define pointers as params • #include <stdio.h> • void swap(int *p, int *q) • { • int tmp; • tmp = *p; • *p = *q; • *q = tmp; • } • int main(void) • { • int i = 3, j = 5; • swap(&i, &j); • printf( “%d %d\n”, i, j ); • return 0; • } Use dereferenced values Pass addresses as arguments
Arrays and Pointers An array name is an address! • a[i] is equivalent to *(a + i) • p[i] is equivalent to *(p + i) • for ( p = a; p < &a[ N ]; ++p ) • sum += *p; • is equivalent to: • for ( i = 0; i < N; ++i ) • sum += a[i]; The main difference between the two: a pointer can be modified, an array cannot, it is a CONSTANT pointer!
Pointer Arithmetic and Element Size • double a[2], *p = NULL, *q = NULL; • p = a; • q = p +1; • printf(“%d\n”, q - p); • printf(“%d\n”, (int)q - (int)p); points to the base of the array equivalent to q = &a[ 1 ] 1 is printed sizeof(dobule)==8 is printed
Passing an array to a function • double sum(double a[], int n) • { • int i = 0; • double sum = 0.0; • for ( i = 0; i < n; ++i ) • sum += a[i]; • return sum; • } • What will sum(a+3, 3) compute? Base address is passed call by value.
Strings s • char s[] = “abcde” #include <string.h> char *strcat(char *s1, const char *s2); int strcmp(const char *s1, const char *s2); char *strcpy(char *s1, const char *s2); unsigned strlen(const char *s);
An implementation example • char *strcat( char *s1, const char *s2 ) • { • register char *p = s1; • while ( *p ) • ++p; • while ( *p++ = *s2++ ) ; • return s1; • }
Dynamic memory allocation • #include <stdlib.h> • Functions work with void * - a generic pointer; all return NULL on failure • size_t is typically unsigned int • void *calloc( size_t n, size_t el_size) • //all allocated bytes are initialized to zero • void *malloc( size_t size ) • //no initialization • void free( void *ptr )
Lexicographical sort (lexi-sort.c) an array of pointers • int main(void) • { • char *w[N]; • char word[MAXWORD]; • int n = 0, i = 0; • for ( i = 0; scanf("%s", word) == 1; ++i ) • { • if ( i >= N ) { • printf( “Sorry, at most %d words can be sorted.”, N ); • exit(1); • } • w[i] = calloc(strlen(word) + 1, sizeof(char)); • assert(w[i]!=NULL); • strcpy(w[i], word); • } work space Check allocation
Lexicographical sort • n = i; • sort_words( w, n ); • for ( i = 0; i < n; ++i ) • printf( “%s\n”, w[i] ); • return 0; • } print the sorted words
Lexicographical sort n elements to be sorted • void sort_words( char *w[], int n ) • { • int i = 0, j = 0; • for ( i = 0; i < n; ++i ) • for ( j = i + 1; j < n; ++j ) • if ( strcmp(w[i], w[j]) > 0 ) • swap( &w[i], &w[j] ); • } • void swap( char **p, char **q ) • { • char *temp = NULL; • temp = *p; • *p = *q; • *q = temp; • }
Arguments to main() (echo.c) • #include <stdio.h> • void main(int argc, char *argv[]) • { • int i = 0; • printf( “argc = %d\n”, argc ); • for ( i = 0; i < argc; ++i ) • printf( “argv[%d] = %s\n”, i, argv[i] ); • }
Multidimensional Arrays • int a[5][2]={{1,2},{3,4},{5,6},{7,8},{9,10}}; • a[i][j] is equivalent to *(&a[0][0]+2*i+j) • What is **(a+3) ? • What is *(a[2]+1) ?
Functions as arguments • double sum_square( double f(double), int m, int n ) • { • int k = 0; • double sum = 0.0; • for ( k = m; k <= n; ++k ) • sum += f(k) * f(k); • return sum; • } • double sum_square( double (*f)(double), int m, int n ) • { • .....
Functions as arguments • #include <stdio.h> • #include <math.h> • double f(double), sin(double), sum_square(double (*)(double), int, int); • int main(void) • { • printf( “%s%.7f\n%s%.7f\n”, • “ First computation: ”, sum_square(sin, 2, 13), • “Second computation: ”, sum_square(f, 1, 10000)); • return 0; • } • double f(double x) • { • return 1.0 / x; First computation: 5.7577885 • } Second computation: 1.6448341
The qsort function (int-qsort.c) • qsort's prototype in stdlib.h: • void qsort(void *array, • size_t n_elem, • size_t elem_size, • int compare(const void *, const void *)); • compare(a,b) returns negative int if a<b • returns 0 if a=b • returns positive int if a>b
// qsort an array of ints • #include <stdio.h> • #include <stdlib.h> • #include <assert.h> • #define KEYSIZE 16 • int compare_int(const void *p1, const void *p2); • void print_array(char *title, int *key, int n_elem); • int main(void) • { • int key[] = { 4, 3, 1, 67, 55, 8, 0, 4, -5, 37, 7, 4, 2, 9, 1, -1 }; • print_array("before ", key, KEYSIZE); • qsort(key, KEYSIZE, sizeof(int), compare_int); • print_array("after ", key, KEYSIZE); return 0; • }
void print_array(char *title, int *key, int n_elem) • { • int i; • printf("\n %s:\n",title); • for (i = 0; i < n_elem; ++i) • printf("%4d", key[i]); • putchar('\n'); • } • // the compare function to be passed as a parameter to qosrt • int compare_int(const void *p1, const void *p2) • { • const int *q1 = p1, *q2 = p2; • return ((*q1)-(*q2)); • }
Linked lists • typedef struct list { • int data; • struct list * next; • } ll; • void insert( ll *p, int a ) { //assume p!=NULL • struct list *q = p->next; • p->next = (ll *)malloc( sizeof( ll ) ); • assert(p->next != NULL); • p->next->data = a; • p->next->next = q; • } data next
Linked lists • void remove( ll *p ) { //assume p,p->next != NULL • ll *q = p->next; • p->next = q->next; • free( q ); • }
LINKED • #include <stdio.h> • #include <stdlib.h> • #include <assert.h> • typedef char DATA; • struct linked_list • { • DATA d; • struct linked_list *next; • }; • typedef struct linked_list ELEMENT; • typedef ELEMENT*LINK; We will use chars in the example
Iterative List Creation • LINK string_to_list( char s[] ) • { • int i = 0; • LINK head = NULL, tail = NULL; • if ( s[0] != ‘\0’ ) • { • head = ( ELEMENT* )malloc( sizeof( ELEMENT ) ); • head→d = s[0]; • tail = head; String is not empty
for ( i=1; s[i] != ‘\0’; ++i ) • { • tail→next = ( ELEMENT* )malloc( sizeof( ELEMENT ) ); • tail = tail→next; • tail→d = s[i]; • } • tail→next = NULL; • } • return head; • } insert elements at the end of the list mark the end of the list
List deletion (recursive) • void delete_list (LINK head) • { • if( head!= NULL ) { • delete_list( head->next ); • free( head ); • } • } Free only after using the pointer