Pointers - asishm.myweb.cs.uwindsor.caasishm.myweb.cs.uwindsor.ca/cs141/S13/lecs/pointers.pdf ·...
Transcript of Pointers - asishm.myweb.cs.uwindsor.caasishm.myweb.cs.uwindsor.ca/cs141/S13/lecs/pointers.pdf ·...
Pointers
60-141: Introduction to Algorithms and Programming II School of Computer Science
Term: Summer 2013 Instructor: Dr. Asish Mukhopadhyay
What’s a pointer ?
• A pointer is a variable that contains the address of another variable
• Thus it provides indirect access to the value of a variable
7
7
The pointer countPtr indirectly references a variable that contains the value 7
The name count directly references a variable that contains the value 7
countPtr
count
count
Defining pointers
• Like any other variable in C, a pointer must also be declared before use
• Definition format
• Above, countPtr is a pointer to a variable of type integer
• Alternate interpretation of the defintion is that expression *countPtr is of type int
int *countPtr;
Defining pointers
• Since a pointer can point to a variable of any type, the generic definition format is
• Thus * is called the indirection operator
data_type *ptr;
Initializing a pointer
• A pointer can be assigned the value
– NULL, to indicate that it points to nothing
– The address of a variable using the address & operator
– The value 0 ( this is the only integer that can be directly assigned to a pointer)
The address operator
• The address operator & applied to a variable gives the address of that variable
• Thus given the definitions
the assignment
puts the address of x in xPtr
int x
int *xPtr
xPtr = &x
A demo int main( void )
{
int a; // a is an integer
int *aPtr; // aPtr is a pointer to an integer
a = 7;
aPtr = &a; // set aPtr to the address of a
printf( "The address of a is %p"
"\nThe value of aPtr is %p", &a, aPtr );
printf( "\n\nThe value of a is %d"
"\nThe value of *aPtr is %d", a, *aPtr
);
printf( "\n\nShowing that * and & are
complements of "
"each other\n&*aPtr = %p"
"\n*&aPtr = %p\n", &*aPtr, *&aPtr );
} // end main
Passing arguments to functions by reference
• Computing n3
– Solution without pointers
int cubeByValue( int n )
{
return n * n * n
}
Solution with pointers void cubeByReference( int *nPtr ); // function prototype int main( void ) { int number = 5; // initialize number printf( "The original value of number is %d", number ); // pass address of number to cubeByReference cubeByReference( &number ); printf( "\nThe new value of number is %d\n", number ); } // end main // calculate cube of *nPtr; actually modifies number in main void cubeByReference( int *nPtr ) { *nPtr = *nPtr * *nPtr * *nPtr; // cube *nPtr } // end function cubeByReference
Using the const qualifier with pointers
• The const qualifier used with a variable indicates to the compiler that the value of the variable should not be modified
Pointers and function arguments
• 4 ways to do this:
– Non-constant pointer to non-constant data
– Non-constant pointer to constant data
– Constant pointer to non-constant data
– Constant pointer to constant data
Non-constant pointer to non-constant data
• Example:
– Convert a string to uppercase
Non-constant pointer to non-constant
data #include <stdio.h>
#include <ctype.h>
void convertToUppercase( char *sPtr ); // prototype
int main( void )
{
char string[] = "cHaRaCters and $32.98"; // initialize
// char array
printf( "The string before conversion is: %s", string );
convertToUppercase( string );
printf( "\nThe string after conversion is: %s\n", string
);
} // end main
Pointer and data non-constant
// convert string to uppercase letters
void convertToUppercase( char *sPtr )
{
while ( *sPtr != '\0' ) { // current
character is not '\0'
*sPtr = toupper( *sPtr ); // convert to
uppercase
++sPtr; // make sPtr point to the next
character
} // end while
} // end function convertToUppercase
Non-constant pointer to constant data
• String printing
#include <stdio.h>
void printCharacters( const char *sPtr );
int main( void )
{
// initialize char array
char string[] = "print characters of a
string";
puts( "The string is:" );
printCharacters( string );
puts( "" );
} // end main
Non-constant pointer to constant data
void printCharacters( const char *sPtr )
{
// loop through entire string
for ( ; *sPtr != '\0'; ++sPtr ) { // no
initialization
printf( "%c", *sPtr );
} // end for
} // end function printCharacters
Constant pointer to non-constant data
// Attempting to modify a constant pointer to
non-constant data.
#include <stdio.h>
int main( void )
{
int x; // define x
int y; // define y
// ptr is a constant pointer to an integer
that can be modified
// through ptr, but ptr always points to the
same memory location
int * const ptr = &x;
*ptr = 7; // allowed: *ptr is not const
ptr = &y; // error: ptr is const; cannot
assign new address
} // end main
Constant pointer to constant data
int main( void )
{
int x = 5; // initialize x
int y; // define y
// ptr is a constant pointer to a constant
integer. ptr always
// points to the same location; the integer at
that location
// cannot be modified
const int *const ptr = &x; // initialization is
OK
printf( "%d\n", *ptr );
*ptr = 7; // error: *ptr is const; cannot assign
new value
ptr = &y; // error: ptr is const; cannot assign
new address
} // end main
The swap function
• The swap function is used by comparison-based sorting methods to swap two out-of-order elements of a list (represented as an array)
• The call swap(a,b) to the following function does not work
void swap(int x, int y) { int temp temp = x; x = y; y = temp; }
The swap function
• Instead the call swap(&a,&b) to the function below works
void swap(int *px, int *py) { int temp temp = *px; *px = *py; *py = temp; }
Swap Pictorially
In caller
In swap
py
b
px
a
Bubble Sort again
• We use the swap routine of the previous slide to re-work bubble sort (see Fig. 7.15 of your text-book)
Bubble Sort
int main( void ) { // initialize array a int a[ SIZE ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 } // print array before a call to bubble sort bubbleSort( a, SIZE ); // sort the array //print array before a call to bubble sort } // end main
Bubble Sort void bubbleSort( int * const array, size_t size ) { void swap( int *element1Ptr, int *element2Ptr ); // prototype unsigned int pass; // pass counter size_t j; // comparison counter // loop to control passes for ( pass = 0; pass < size - 1; ++pass ) { // loop to control comparisons during each pass for ( j = 0; j < size - 1; ++j ) { // swap adjacent elements if they’re out of order if ( array[ j ] > array[ j + 1 ] ) { swap( &array[ j ], &array[ j + 1 ] ); // swap function shown earlier } // end if } // end inner for } // end outer for } // end function bubbleSort
Pointers and Arrays
• In C, pointers and arrays are intimately related
• Any operation that can be achieved by array subscripting can be done by pointers
• Given the definitions :
int a[10];
int *pa;
Pointers and Arrays • The assignment
puts in pa the address of the first element of the array
• Pictorially, we have
pa = &a[0];
pa:
a[1] a[0]
a:
Pointers and Arrays
• Now the assignment
copies the contents of a[0] into x
int x = *pa
Pointers and Arrays
• If pa points to a particular element in the array then
– pa+1 points to the second and
– pa + i points to the (i+1)-th element of the array
• Pictorially :
pa:
a[1] a[0]
a:
pa+2 pa+1
Pointers and Arrays
• The assignment
pa = &a[0]
can be simply written as
pa = a,
since a is a pointer to the first element of the array
Pointers and Arrays
• In fact, a reference to a[i] can be reinterpreted as *(a+i)
• Thus,
&a[i] = &*(a+i) = (a+i)
• However, since an array name is not a variable
a = pa
or
a++
are all illegal
An example
/* strlen: returns length of a string */
int strlen( char *s)
{
int n;
for ( n = 0; *s != ‘\0’; s++)
n++;
return n;
}
Pointer Arithmetic
• If pointers p and q point to members of the same array , then p op q is valid for all relational operators
• Pointer subtraction is also valid in this situation. Here is another version of strlen that uses this
Pointer Arithmetic
/* strlen: return length of a string */
int strlen( char *s)
{
char *p = s;
while ( *p != ‘\0’)
p++;
return p - s; // pointer subtraction
}
Character pointers and functions
• A string constant, written as
“ I am a string”
is an array of characters terminated by ‘\0’
• Most common use as arguments of printf
printf(“hello, world \n”);
Character pointers and functions
• Given the declaration
char *pmessage;
then
pmessage = “Now is the time”
assigns to pmessage a pointer to the character array
Character pointers and functions
• Difference between the definitions
char amessage [] = “Now is the time”
pmesssage = “Now is the time”
• amessage [] is an array just large enough to hold the string; individual characters may be changed but amessage will always refer to the same storage
Character pointers and functions
• On the other hand, pmessage is a pointer to a string constant; subsequently, it may be used to point elsewhere but the contents of the string cannot be modified
Now is the time \0
Now is the time \0
pmessage:
amessage:
Various versions of strcpy (1)
• Array version
void strcopy(char *s, char *t)
{
int i = 0;
while ((s[i] = t[i]) != ‘\0’)
i++;
}
Various versions of strcpy (2)
• Pointer version
void strcopy(char *s, char *t)
{
while ((*s = *t) != ‘\0’){
s++;
t++;
}
}
Various versions of strcpy (3)
• A more compact pointer version
void strcopy(char *s, char *t)
{
while ((*s++ = *t++) != ‘\0’)
;
}
Various versions of strcpy (4)
• A still more compact pointer version
void strcopy(char *s, char *t)
{
while (*s++ = *t++);
}
strcmp: comparing char strings (1)
• Array version
/*strcmp: returns < 0 if s < t, 0 if s ==t,
> 0 if s > t */
int strcmp(char *s, char *t)
{
int i;
for( i = 0; s[i] == t[i]; i++)
if (s[i] == ‘\0’)
return 0;
return s[i] – t[i];
}
strcmp: comparing char strings (2)
• Pointer version
/*strcmp: returns <0 if s < t, 0 if s==t,
>0 if s >t */
int strcmp(char *s, char *t)
{
for( ; *s == *t; s++, t++)
if (*s == ‘\0’)
return 0;
return *s – *t;
}
Array of pointers
• Being variables, pointers can be stored in arrays as other variables of type int or char, for example
• Thus, array of pointers
Application to lexicographic sorting
defghi jklmnopqrst
abc
defghi jklmnopqrst
abc
Only pointer values are exchanged
Lexicographic Order
• Let A be a finite alphabet set.
• For example, {a, b, c,…, z}, the set of lower case letters of the English language.
• The listing defines an order, namely
– a < b < c < …. < z ( read < as “precedes” )
• This can be used to order two strings s1 and s2 over A
Ordering strings
• Let
– l be the length of s1 and
– si,j be the j-th letter of the i-th string
• We say s1 < s2 iff there exists (a leftmost) index i ≤ l such that
– s1,i < s2,i or
– s1,j = s2,j for j = 1,2,3, …, l
Algorithm
• Input consists of several lines, with one string per line
1.Read all the lines of input 2.Sort them 3.Print them in order
Reading input
• C- code
Code for reading input (1)
#include <stdio.h> #define MAXLEN 1000 int getline(char *, int); // prototypes char *alloc(int); /* readlines: read input lines */ int readlines(char *lineptr[], int maxlines) { int len, nlines; char *p, line[MAXLEN];
Code for reading input (2)
nlines = 0; while((len = getline(line,MAXLEN)) > 0) if (nlines >= maxlines || (p = alloc(len)) == NULL) return -1; else { line[len-1] = '\0'; /*delete newline symbol*/ strcpy(p, line); lineptr[nlines++] = p; } return nlines; }// readline
Code for reading input (3)
#include <stdio.h> int getline(char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c = getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = '\n'; s[i] = ‘\0’; return i; }
Code for reading input (4)
// allocate storage from buffer #define ALLOCSIZE 10000 /* size of available space */ static char allocbuf[ALLOCSIZE]; static char *allocp = allocbuf; char *alloc(int n) /* return pointer to n characters */ { if (allocbuf + ALLOCSIZE - allocp >= n){ allocp += n; return allocp -n; /* the old p */ } else return 0; /* not enough room */ }
Storage allocation model
After call to allocate:
Before call to allocate:
allocbuf:
allocbuf:
In use
In use
Free
Free
allocp:
allocp:
ALLOCSIZE
Sorting lines
• C-code
Sorting code (1)
#include <stdio.h> #include <string.h> void swap(char *lineptr[], int, int); // prototype void bubbleSort( char *lineptr[], int size ) { unsigned int pass; // pass counter size_t j; // comparison counter
Sorting code (2)
// loop to control passes for ( pass = 0; pass < size - 1; ++pass ) { // loop to control comparisons during each pass for ( j = 0; j < size - 1; ++j ) { if(strcmp(lineptr[j], lineptr[j+1]) > 0) swap(lineptr, j, j+1); } // end inner for } // end outer for } // end function bubbleSort
Output lines
• C-code
Code to Output lines
/* writelines: write output lines */ void writelines(char *lineptr[], int nlines) { int i; for(i = 0; i < nlines; i++) printf("%s\n", lineptr[i]); }
Main.c (1) #include <stdio.h> #include <string.h> #include "getline.c" #include "readLines.c" #include "writeLines.c" #include "sorting.c" #include "allocateStorage.c" #define MAXLINES 5000 char *lineptr[MAXLINES]; int readlines(char *lineptr[], int nlines); void writelines(char *lineptr[], int nlines); void bubbleSort(char *lineptr[], int nlines);
Main.c (2)
int main(void) { int nlines; /*number of lines read */ if ((nlines = readlines(lineptr, MAXLINES)) >= 0){ bubbleSort(lineptr, nlines ); writelines(lineptr, nlines); return 0; }else { printf("error: Input too big to sort \n"); return; } } // end main
Initializing pointer arrays
• By example:
– A function month_name(n) which returns a pointer to a character string containing the name of the n-th month
Initializing pointer arrays
char *month_name(int n) { static char *name[] = { “illegal month”, “January”, “February”, “March”, “April”, “May”, “June”, “July”, “August”, “September”, “October”, “November”, “December” } return (n < 1 || n > 12 ) ? name[0] : name[n]; }
Pointers to functions
• A pointer to a function contains the address of the function in memory
• Such a pointer can be assigned, passed to functions, returned by functions and so on
• Pointer to function are useful for designing menu-driven systems
Menu-driven system
• A generic example: Fig.7.28 from your text book
• Reading Assignment:
– Study Fig. 7.26 of your textbook