CS 192
Lecture 12
Winter 2003
December 31, 2003 - January 1, 2004
Dr. Shafay Shamail
Pointer• Points to an item
• Holds the memory address of the item
• Has its own memory storage
• Occupies space in memory
• Hence can itself be accessed too
• Allows C/C++ to support dynamic memory allocation
• If x contains the address of y, x is said to “point to” y
• Pointer variables are declared as
type *var-name;
e.g. int *p; pointer p contains the memory address of an int variable
float *fl; points to a float variable
Assumptions
• characters are one byte in length
• integers are four bytes long
• floats are four bytes long
• doubles are eight bytes long
& address of
* value at address
&a address of variable a
*p contents of location pointed to by variable p
Pointer Operators
• & (address operator)– a unary operator that returns the memory address of its
operand.
int balance = 350;
int *balptr;
balptr = &balance;• This address is the location of the variable in memory,
it has nothing to do with the value of balance.
Pointer Operators
• * (indirection operator)– Is the complement of &.– It is a unary operator that returns the value of
variable located at address specified by its operand.
int balance = 350;
int *balptr;
balptr = &balance;
int value;
value = *balptr;
// what does value contain?
Pointer Operators
Pointers• int a=1, b=2, *p;
• Picture in memory at this point:
• p=&a; //p is assigned the address of a
• b=*p; //b is assigned the value pointed to by p
As p points to a, the statement b=*p is equivalent to b=a
a b p
1 2
a b p
1 2 ?
a b p
1 1
int main()
{
int balance;
int *balptr;
int value;
balance = 3200;
balptr = &balance;
value = *balptr;
cout << "balance is: " << value << '\n';
cout << "Memory address where balance is stored is: ”
<< balptr << endl;
return 0;
}
Pointer Operators
Output
balance is: 3200
Memory address where balance is stored is: 0012FF7C
(Note memory address may be different when you run it on your machine)
value = *balptr;
• The compiler transfers the proper number of bytes according to base type.
int *p;
double f;
// ...
p = &f; // ERROR
Base Type
int *p;
int x = 12;
p=&x;
cout << x << endl;
//Assign a value to the location pointed to by p
*p = 101;
cout << x << endl; //what is value of x?
cout << *p << endl;
cout << p << endl;
cout << &x << endl;
Assigning Values Through a Pointer
Assigning values through a pointer
121011010012FF780012FF78
(*p)++; //increment value to the location pointed to by p
int main()
{
int *p, num;
p = #
*p = 454;
cout << num << ' ';
(*p)++; /* parentheses are necessary because * operator
has lower precedence than ++operator */
cout << num << ' ';
(*p) - -;
cout << num << '\n';
return 0;
} //Output?
Assigning Values Through a Pointer
//Output is 454 455 454
Assigning Values Through a Pointer
• There are only four arithmetic operators that can be used on pointers: ++, --, +, -
• Let p1 be an integer pointer which contains the address 5000
• p1++; // now p1 will be 5004
• Each time p1 is incremented, it shall point to the next integer.
• p1--; will cause p1 to be 4996 if initially it was 5000.
Pointer Arithmetic
• Let p1 be a char pointer which contains the address 4000
• p1++; // now p1 will be 4001
• Each time p1 is incremented, it shall point to the next character.
• p1--; will cause p1 to be 3999 if initially it was 4000.
• Pointer of type other than char shall increase or decrease by length of base type.
Pointer Arithmetic
• You cannot add two pointers
• You can subtract two pointers (if they are of same base type).
• Other than – addition or subtraction of a pointer and an integer, OR– csubtraction of two pointers,
no other arithmetic operations can be performed on pointers.
• You cannot add or subtract float or double values.
Pointer Arithmetic
int main()
{
int *iptr, a; //which is pointer to int? which is int?
double *fptr, b;
int x;
a = 10;
b = 20;
iptr = &a;
fptr = &b;
for ( x = 0; x < 10; x++)
cout << iptr+x << " " << fptr+x << '\n';
return 0;
}
Pointer Arithmetic
• In C++, there is a close relationship between pointers and arrays.
• Two examples
Pointers and Arrays
int main()
{
int *iptr;
int iarray[4] = { 5, 6, 7, 8};
iptr = iarray;
cout << iptr << " " << iarray << “\n”;
cout << iptr[0] << " " << iarray[0] << “\n”;
cout << *(iptr+1) << " " << iarray[1] <<“\n”;
return 0;
} //Output?
Pointers and Arrays
Output is:
0012FF6C 0012FF6C
5 5
6 6
Pointers and Arrays
int b[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int *bptr = b; // set bPtr to point to array b
int *b2ptr = b+5; /* set b2Ptr to point to sixth
element of array b */
cout << "b[" << 5 << "] = " << b[5] << endl;
cout << "*b2ptr = " << *b2ptr << endl;
cout << "(b2ptr - bptr) = " << (b2ptr - bptr) << endl;
Pointers and Arrays
int b[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int *bptr = b; // set bPtr to point to array b
int *b2ptr = b+5; /* set b2Ptr to point to sixth
element of array b */
cout << "b[" << 5 << "] = " << b[5] << endl;
cout << "*b2ptr = " << *b2ptr << endl;
cout << "(b2ptr - bptr) = " << (b2ptr - bptr) << endl;
Output is:
b[5] = 60
*b2ptr= 60
(b2ptr - bptr) = 5
Pointers and Arrays
int i1[4]={5,6,7,8};int i2[4]={1,2,3,4};i2=i1; //NOT ALLOWED
Why? /*name of array is a constant that points to beginning of array*/
char str1[]=“i am a string”;char str2[]=“i am a string”;str1==str2; //WRONG way of string comaprison
Pointers may be compared in C++ using relational operators like >, >=, <, <=, == etc, but they must have some relationship to be meaningful
Pointers and Arrays
int i1[4]={5,6,7,8};int i2[4]={1,2,3,4};
int*ptr1=i1;int *ptr2;ptr2=ptr1; //this is ok
Pointers and Arrays
int i1[4]={5,6,7,8};What is wrong with the following statement?i1++;
//The following is okint *iptr=i1;iptr++;cout<<*iptr;
//The following is ok *(i1+3) = 100; // This is OK because i1 has not changed
Pointers and Arrays
int b[] = {10, 20, 30, 40}; int *bptr = b; // set bptr to point to array b
cout << "Array b printed with:" << endl << "Array subscript notation" << endl;
for (int i = 0; i <= 3; i++) cout <<b[i] << endl;
cout << "Pointer subscript notation" << endl;
for (i = 0; i <= 3; i++) cout << bptr[i] << endl;
Using Subscripting and Pointer Notations with Arrays
int offset; cout << "Pointer/offset notation where" << endl << "the pointer is the array name" << endl;
for (offset = 0; offset <= 3; offset++) cout << *(b + offset) << endl;
cout <<"Pointer/offset notation" << endl;
for (offset = 0; offset <= 3; offset++) cout << *(bptr + offset) << endl;
Using Subscripting and Pointer Notations with Arrays
int *iptr; int iarray[4] = {5,6,7,8}; iptr = iarray;
cout << iptr << " " << iarray <<endl;
cout << iptr[0] << " " << iarray[0]<< endl ; cout << &iptr[0] << " " << &iarray[0]<< endl;
Using Subscripting and Pointer Notations with Arrays
int main(){
int a[3] = {10, 20, 30}; double b[3] = {10.5, 20.5, 30.5}; int *iptr; double *fptr; int x, size=3;
iptr = a; //name of array is a constant that points to beginning of array fptr = b;
for(x=0; x<size; x++) { cout << iptr+x << " " << fptr+x << '\n'; cout <<*( iptr+x) << " " <<*( fptr+x) << '\n'; cout << *iptr+x << " " << *fptr+x << '\n'; }
return 0; } //pointer-add example
Pointer Arithmetic
Output:0x0012FF74 0x0012FF5C10 10.510 10.50x0012FF78 0x0012FF6420 20.511 11.50x0012FF7C 0x0012FF6C30 30.512 12.5
Pointer Arithmetic
int a[3] = {1, 2, 3};int *iptr; iptr = a;
//what is the difference between *iptr++ and (*iptr)++ and *(iptr++)?
cout<<*iptr++; cout<<*++iptr; cout<<(*iptr)++; cout<<++(*iptr); cout<<*(iptr++); cout<<*(++iptr);
Pointer Arithmetic
int a[3] = {1, 5, 9};int *iptr; iptr = a;
//what is the difference between *iptr++ and (*iptr)++ and *(iptr++)?
Output: (looking at each statement independently)
cout<<*iptr++; // 1 cout<<*++iptr; // 5 cout<<(*iptr)++; // 1 cout<<++(*iptr); // 2 cout<<*(iptr++); // 1 cout<<*(++iptr); // 5
Pointer Arithmetic
int a[3]={1, 5, 9};int *iptr; iptr = a;
Self Test: what is output if the statements are executed one after the other? //Be-careful is there array overrun? garbage values?
cout<<*iptr++; cout<<*++iptr; cout<<(*iptr)++; cout<<++(*iptr); cout<<*(iptr++); cout<<*(++iptr);
Self Test: Pointer Arithmetic
What is wrong here?
int* myptr;*myptr=32;
Self Test-2
What is output here?int x=235;int a[3]={1, 5, 9};cout<<*(&x);cout<<*(&a[1]);
Self Test
Pointers & Arrays• Is anything wrong with the following:
int num[3]; int i; for(i=0; i<10; i++) { *num = i; // is this OK? num++; // is this OK? }
• Can’t modify num. Can’t modify a pointer constant (an array’s name)
• But this is ok:
int num[3]= {0, 1, 2}; int *p = num; *(p++);
Pointers & Strings• A string constant, like an array name, is treated by the
compiler as a pointer
char *p = “abc”;cout<<p<<endl<<p+1<<endl<<*p<<endl<<*(p+1); //output?
• abc bc a b
• p is assigned the base address of the character array “abc”. String printed till null character, as usual
• Can we use such expressions: “abc”[1] and *(“abc” + 2)• Of course, output is b and c respectively
a b c \0
p
Pointer Comparisons• Pointers may be compared using relational operators (e.g. ==, <, >). • To be meaningful, pointers should be of same type
int num[10]; int *start, *end; start = num; end = &num[9]; while(start!=end) { cout << "Enter a number: "; cin >> *start; start++; } start = num; /* reset the starting pointer */ while(start!=end) { cout << *start << ' '; start++; }
…
start
end
num
Arrays of Pointers
• Can sure do that like other data typese.g. int *zztop[10]; //array of 10 int pointers
• Now, say int var; zztop[3]=&var; *zztop[3];• Arrays of pointers to strings commonly used
char *fortunes[] = { "Soon, you will come into some money.\n", "A new love will enter your life.\n", "You will live long and prosper.\n", "Now is a good time to invest for the future.\n", "A close friend will ask for a favor.\n" };
cout << fortunes[1] << endl << fortunes<<endl << *(fortunes) << endl << *(fortunes[2]) << endl;
• Output: A new love will enter your life
0012FFC6Soon, you will come into some moneyY
Arrays of Pointers• Two dimensional string pointers e.g. C++ dictionary
char *keyword[][2] = { "for", "for(initialization; condition; increment)", "if", "if(condition) ... else ...", "switch", "switch(value) { case-list }", "while", "while(condition) ...", // add the rest of the C++ keywords here "", "" // terminate the list with nulls };
int main(){ char str[80]; int i; cout << "Enter keyword: "; cin >> str;
for(i=0; *keyword[i][0]; i++) if(!strcmp(keyword[i][0], str)) cout << keyword[i][1]; return 0; }
Array of Strings vs. Array of Pointers• Spot the difference:
char movies[5][20] ={“Godfather”, “Maula Jatt”, “A Fish Called Wanda”, “Blade Runner”, “Spiderman”};
char *movies[5] = {“Godfather”, “Maula Jatt”, “A Fish Called Wanda”, “Blade Runner”, “Spiderman”};
• In the first case, each column is 20 characters wide due to the longest movie name; wasted space
• In the second case, the strings are placed contiguously in memory without wasting space; pointers in the array movie point to them
The new operator
int *x_ptr = new int;
OR
int *xptr;xptr = new int;//heap
Dynamic Allocation
int *xptr=new int;*xptr = 73;
int *x2ptr = new int;*x2ptr = 65;
Dynamic Allocation
What is wrong here?
int *xptr = new int;*xptr = 73;
int *x2ptr;*x2ptr=65;
Dynamic Allocation
int *xptr = new int;*xptr = 73;
int *x2ptr;x2ptr = xptr;*x2ptr = 65;
Dynamic Allocation
//What is wrong here?
int *xptr = new int;*xptr = 73;
int *x2ptr = new int;x2ptr = xptr;*x2ptr = 65;
//memory leak
Dynamic Allocation
int *myptr = new int(73);cout << *myptr;
delete myptr;
Dynamic Allocation
const int SIZE = 10;double *ptr = new double[SIZE]; /*10 element array*/int i;
for (i=0; i<SIZE; i++){
ptr[i] = 2.0*i;}
for (i=0; i<SIZE; i++){
cout << ptr[i] << endl; }
delete []ptr;
Dynamic Allocation
int *intPtr; int i[10]={10,11,12,13,14,15,16,17,18,19}; char *charPtr; char c[]="We are testing char pointers";
intPtr = i; charPtr = c;
cout << i <<" "<< c << endl; cout << intPtr << " " << charPtr << '\n'; cout << *intPtr <<" "<< i[0] << '\n';
Char Pointers
0x0012FF54 We are testing char pointers0x0012FF54 We are testing char pointers10 10
char pointers
When the compiler encounters a string constant, it stores it in the program string table and generates a pointer to the string.
char *s; s = "Pointers are fun to use.\n"; cout << s;
char s2[]="Pointers are fun to use.\n"; cout << s2;
Char Pointers
int size;cin>>size;int* array=new int[size];int i;
for (i=0; i<size; i++){
array[i]=2*i;}
for (i=0; i<size; i++){
cout<<array[i]<<endl; }
delete []array;
Pointers - Dynamic Allocation
• This program scans the input string, copying
characters from the string into another array, called token, until a space is encountered. It prints the token and repeats the process until null at end of string is encountered.
• e.g “This is a test:
This
is
a
test
Tokenizing Example
int main()
{
char str[80], token[80];
int i, j;
cout << "Enter a sentence: ";
gets(str); // Read a token at a time from the string.
for(i=0; ; i++)
{ /* Read characters until either a space or the null terminator is encountered.
*/
for(j=0; str[i]!=' ' && str[i]; j++, i++)
{
token[j] = str[i];
}
token[j] = '\0'; // null terminate the token
cout << token << '\n';
if(!str[i])
break;
}
return 0;
}
SELF_TEST:Tokenizing Example Using Arrays
char str[80], token[80];
int i=0, j=0;
cout << "Enter a sentence: ";
cout.flush();
gets(str); // Read a token at a time from the string.
Tokenizing Example Using Arrays
while(str[i])
{
j=0;
while(str[i]!=' ' && str[i])
{
token[j]=str[i];
i++;
j++;
}
token[j]='\0';
if(str[i])
i++;
cout << token << '\n';
}
Tokenizing Example Using Arrays
int main()
{
char str[80], token[80];
char *p, *q;
cout << "Enter a sentence: ";
gets(str);
p = str;
Tokenizing Example Using Pointers
// Read a token at a time from the string.
while(*p)
{
q = token; // set q pointing to start of token
/* Read characters until either a space or the null
terminator is encountered. */
while(*p!=' ' && *p)
{
*q = *p;
q++; p++;
}
if(*p)
p++; // advance past the space
*q = '\0'; // null terminate the token
cout << token << '\n';
}
return 0;
}
Tokenizing Example Using Pointers