BIL 104E Introduction to Scientific and Engineering Computing Lecture 9
Pointer Expressions and Pointer Arithmetic Pointer arithmetic is a convenient way for changing the value of a pointer in increments of the size of its base type – Increment/decrement pointer ( ++ or -- ) – Add an integer to a pointer( + or +=, - or -= ) – Pointers may be subtracted from each other – Operations meaningless unless performed on an array Lecture 92
Pointer Expressions and Pointer Arithmetic 5 element int array on machine with 4 byte int s – vPtr points to first element v[0] at location ( vPtr = 3000 ) – vPtr +=2; sets vPtr to 3008 vPtr points to v[2] (incremented by 2), but machine has 4 byte int s Lecture 93 pointer variable vPtr v[0]v[1]v[2]v[4]v[3] location
Pointer Expressions and Pointer Arithmetic Subtracting pointers – Returns number of elements from one to the other. vPtr2 = &v[2]; vPtr = &v[0]; vPtr2 - vPtr == 2. Pointer comparison ( ) – See which pointer points to the higher numbered array element – Also, see if a pointer points to Lecture 94
Pointer Expressions and Pointer Arithmetic Pointers of the same type can be assigned to each other – If not the same type, a cast operator must be used – Exception: pointer to void (type void * ) Generic pointer, represents any type No casting needed to convert a pointer to void pointer void pointers cannot be dereferenced Lecture 95
The Relationship Between Pointers and Arrays Arrays and pointers closely related – Array name like a constant pointer – Pointers can do array subscripting operations Declare an array b[5] and a pointer bPtr bPtr = b; Array name actually a address of first element OR bPtr = &b[0] Explicitly assign bPtr to address of first element Lecture 96
/* Referencing an array with a pointer*/ #include main() { int *ptr_int; int list_int[10]; int i; for(i=0; i<10; i++) list_int[i] = i + 1; ptr_int= list_int; /* pointer points to the beginning of the array*/ printf( "The start address of the array: 0x%p\n", ptr_int); printf( "The value of the first element: %d\n", *ptr_int); ptr_int= &list_int[0]; printf( "The address of the first element: 0x%p\n", ptr_int); printf( "The value of the first element: %d\n", *ptr_int); return 0; } Lecture 97 The start address of the array: 0x0240FF20 The value of the first element: 1 The address of the first element: 0x0240FF20 The value of the first element: 1
The Relationship Between Pointers and Arrays Element b[n] – can be accessed by *( bPtr + n ) – n - offset (pointer/offset notation) – Array itself can use pointer arithmetic. b[3] same as *(b + 3) – Pointers can be subscripted (pointer/subscript notation) bPtr[3] same as b[3] Lecture 98
#include int main() { int iaArray[4]={2,4,6,8}; int *ipTab = iaArray; int i; for (i=0;i<4;i++) { /* index notation used to access array elements */ printf("%d ",iaArray[i]); /* pointer arithmetic and indirect values are used to access array elements */ printf("%d ",*(iaArray + i)); /* index notation used to access array elements */ printf("%d ",ipTab[i]); /* pointer arithmetic and indirect values are used to access array elements */ printf("%d\n",*(ipTab + i)); } return 0; } Lecture
/* Accessing arrays via pointers */ #include main() { char str[] = "It's a string!"; char *ptr_str; int list[] = {1, 2, 3, 4, 5}; int *ptr_int; /* access char array */ ptr_str= str; printf("Before the change, str contains: %s\n", str); printf("Before the change, str[5] contains: %c\n", str[5]); *(ptr_str+ 5) = 'A'; printf("After the change, str[5] contains: %c\n", str[5]); printf("After the change, str contains: %s\n", str); /* access int array */ ptr_int= list; printf("Before the change, list[2] contains: %d\n", list[2]); *(ptr_int+ 2) = -3; printf("After the change, list[2] contains: %d\n", list[2]); return 0; } Lecture 910 Before the change, str contains: It's a string! Before the change, str[5] contains: a After the change, str[5] contains: A After the change, str contains: It's A string! Before the change, list[2] contains: 3 After the change, list[2] contains: -3
/* Use of array index and pointer notation to access and print a two-dimensional matrix.*/ #include int main() { int a[2][3] = {10,20,30,40,50,60}; int *p,i,j; p = (int *) a; printf("Using pointer notation to access and print array contents (1)\n"); for(i=0;i<2;i++){ for(j=0;j<3;j++) printf("%2d ",*(p+(i*3)+j)); printf("\n"); } printf("Using pointer notation to access and print array contents (2)\n"); for(i=0;i<2;i++){ p = *(a + i); for(j=0;j<3;j++) printf("%2d ",*(p+j)); printf("\n"); } printf("Using array subscripts to access and print array contents\n"); for(i=0;i<2;i++){ for(j=0;j<3;j++) printf("%2d ",a[i][j]); printf("\n"); } return 0; } Lecture 911 Using pointer notation to access and print array contents (1) Using pointer notation to access and print array contents (2) Using array subscripts to access and print array contents
Arrays of Pointers Arrays can contain pointers - array of strings char *suit[4] = {"Hearts", "Diamonds", "Clubs", "Spades" }; – String: pointer to first character – char * - each element of suit is a pointer to a char – Strings not actually in array - only pointers to string in array suit array has a fixed size, but strings can be of any size Lecture 912 suit[3] suit[2] suit[1] suit[0]’H’’e’’a’’r’’t’’s’ ’\0’ ’D’’i’’a’’m’’o’’n’’d’’s’ ’\0’ ’C’’l’’u’’b’’s’ ’\0’ ’S’’p’’a’’d’’e’’s’ ’\0’
/* Using an array of pointers */ #include main() { char *suit[4] = {"Hearths", "Diamonds", "Clubs", "Spades"}; int i, size = 4; /* Print all strings in an array of pointers to strings */ for (i=0; i<size; i++) printf("%s\n", suit[i]); return 0; } Lecture 913 Hearths Diamonds Clubs Spades
Dynamic Memory Allocation There are many cases when the exact sizes of arrays are not known until much later when the programs are actually being executed. The sizes of arrays can be specified in advance, but the arrays can be too small or too big if the numbers of data items that we want to put into the arrays change dramatically at runtime. C provides four dynamic memory allocation functions that can be employed to allocate or reallocate certain memory spaces while the program is running. Also release allocated memory storage can be released as soon as it is not needed: – malloc ( ) function used when allocating memory – calloc( ) function used when allocating memory – realloc( ) function used to increase/decrease an available memory – free( ) function used to free previously allocated memory Lecture 914
malloc() Function The malloc() function is used to allocate a specified size of memory space. The syntax is: #include void *malloc(size_t size); Here size indicates the number of bytes of storage to allocate. The malloc() function returns a void pointer therefore its type is automatically converted to the type of the pointer on the left side of an assignment operator. If the malloc() function fails to allocate a piece of memory space, it returns a null pointer. Normally, this happens when there is not enough memory. Therefore, the returned pointer from malloc() should always be checked before using it Lecture 915 int *iptr = (int *) malloc (sizeof(int)); float *fptr = (float *) malloc (128); char *str = (char *) malloc(sizeof (char x [50]));
calloc() Function calloc() can also be used to allocate a memory storage dynamically. The differences from the malloc() are that the calloc() takes two arguments and that the memory space allocated by calloc() is always initialized to 0. There is no such guarantee that the memory space allocated by malloc() is initialized to 0. The syntax for calloc() is #include void *calloc(size_t nitem, size_t size); Here nitem is the number of items to be saved in the allocated memory space. size gives the number of bytes that each item takes. The calloc() function returns a void pointer too. If calloc() fails to allocate a piece of memory space, it returns a null pointer Lecture 916
realloc() Function realloc() gives a means to change the size of a piece of memory space allocated by malloc(), calloc(), or even itself. The syntax for realloc() is #include void *realloc(void *block, size_t size); Here block is the pointer to the start of a piece of memory space previously allocated. size specifies the total byte number you want to change to. realloc() returns a void pointer. It returns a null pointer if it fails to reallocate a piece of memory space. realloc() is equivalent to malloc() if the first argument passed to realloc() is NULL. The following two statements are equivalent: ptr_flt = realloc(NULL, 10 * sizeof (float) ); ptr_flt = malloc(10 * sizeof (float) ); Lecture 917
free() Function Because memory is a limited resource, you should allocate an exactly sized piece of memory right before you need it, and release it as soon as you don't need it. The allocated memory can be released by calling free(). Also, realloc() can be used as the free() function. This is done by passing 0 to realloc() as its second argument. For instance, to release a block of memory pointed to by a pointer ptr, you can either call the free() function like this: free(ptr); or use the realloc() function in the following way: realloc(ptr, 0); Lecture 918
/* malloc () example */ #include main(){ char *cptr; printf("Pelase Enter a sentence\n"); /* allocate 81 bytes a type cast to char pointer */ cptr =(char *) malloc(sizeof(char)*81); if ( cptr !=NULL ){ gets(cptr); printf("You entered this: %s\n", cptr); free(cptr); } else{ printf("Sorry I am unable to allocate 81 bytes for you \n"); exit(0); } return 0; } Lecture 919
/* calloc () example */ #include main(){ char *cptr; printf("Pelase Enter a sentence\n"); /* allocate 81 bytes a type cast to char pointer */ cptr =(char *) calloc(81,sizeof(char)); if ( cptr !=NULL ){ gets(cptr); printf("You entered this: %s\n", cptr); free(cptr); } else{ printf("Sorry I am unable to allocate 81 bytes for you \n"); exit(0); } return 0; } Lecture 920
/* Using the calloc() function */ #include main() { float *ptr1, *ptr2; int i, n=5; int termination = 1; ptr1 = calloc(n, sizeof(float)); ptr2 = malloc(n * sizeof(float)); if (ptr1 == NULL) printf("malloc() failed.\n"); else if (ptr2 == NULL) printf("calloc() failed.\n"); else { for (i=0; i<n; i++) printf("ptr1[%d]=%5.2f, ptr2[%d]=%5.2f\n", i, *(ptr1 + i), i, *(ptr2 + i)); free(ptr1); free(ptr2); termination = 0; } return termination; } Lecture 921 ptr1[0] = 0.00, ptr2[0] = ptr1[1] = 0.00, ptr2[1] = ptr1[2] = 0.00, ptr2[2] = ptr1[3] = 0.00, ptr2[3] = 0.00 ptr1[4] = 0.00, ptr2[4] =