Pointers

Pointers
Introduction
• Main memory is a sequence of memory locations that are
addressed 0, 1, 2, …
• Pointers are variables that contain memory addresses as
their values.
• A pointer containing an address of some location is said to
be a pointer to that location.
• A pointer variable can have NULL (or 0) value meaning
that the pointer does not point to any memory location.
• Zero is the only integer value that can be assigned to a
pointer.
• Size of pointer is often 4 bytes
Example
int *w;
int t=5;
w=&t;
cout<<t;
cout<<*w;
t++;
cout<<*w;
*w=*w+2;
cout<<t;
float r;
w=&r; //syntax error
w=NULL;
cout<<*w; //run-time error
t=8;
w=&t;
cout<<&t; // FFF4 (for example)
cout<<w;//FFF4
cout<<t;//8
cout<<*t//error
cout<<&*w; //FFF4
cout<<*&w; //FFF4
Pass by address
The program
int sum(int x, int y){return x+y;}
void main(){cout<<sum(2,3);}
can be rewritten as
void sum(int x, int y, int *result){*result= x+y;}
void main(){int x; sum(2,3,&x); cout<<x;}
Pass by reference
The program
int sum(int x, int y){return x+y;}
void main(){cout<<sum(2,3);}
can be rewritten as
void sum(int x, int y, int& result){result= x+y;}
void main(){int x; sum(2,3,x); cout<<x;}
Example
int sumArray(int a[ ], int size){
int I, sum=0; for (I=0; I<size; I++) sum+=a[I]; return sum;
}
//pass by address
void sumArray(int a[ ], int size, int * sumPtr) {
int I, *sumPtr=0; for (I=0; I<size; I++) *sumPtr+=a[I];
}
//pass by reference
void sumArray(int a[ ], int size, int & sum) {
int I; sum=0; for (I=0; I<size; I++) sum+=a[I];
}
Example: A function to swap the values of
two variables using pass by address
void exhange(int *x, int *y){
int temp=*x;
*x=*y;
*y=temp;
}
void main(){
int a=2, b=3; exchange(&a,&b);
cout<<a<<" "<<b; //3 2
}
Example: A function to swap the values of
two variables using pass by reference
void exhange(int &x, int &y){
int temp=x;
x=y;
y=temp;
}
void main(){
int a=2, b=3; exchange(a,b);
cout<<a<<" "<<b; //3 2
}
Pointer operations
A limited set of arithmetic operations may be performed on
pointers:
• Pointers can be compared using equality and relational
operators.
• A pointer can be assigned to another pointer if both
pointers are of the same type. However, a cast operator can
be used to allow this operation.
• The generic pointer (void *) can be assigned to any pointer
and any pointer can be assigned to it. However, a generic
pointer cannot be dereferenced.
• To dereference a void pointer it must be type casted to
some pointer type.
Pointer operations (Cont)
•
•
•
•
A pointer may be incremented (++) or decremented (--).
An integer may be added to a pointer (+ or +=).
An integer may be subtracted from a pointer (- or -=).
One pointer may be subtracted from another. The result is
equal to the difference between the pointers values divided
by data type size.
Example
int x;
int *y=&x;
y++; //increases y by 2
y+=5; //increases y by 10
double z;
double *w=&z;
w--; //decreases w by 8
w-=5; //decreases w by 40
The relationship between pointers and arrays
• An array name is considered as a constant
pointer that always points to the first
element in the array.
• Pointers can be used to do any operations
involving array subscribing.
Example
int b[5], *bPtr;
b++; //compiler error
b=bPtr; //compiler error
bPtr=b;
Is equivalent to:
bPtr=&b[0];
if (b==&b[0]) …//always true
Example (Cont)
b[3]
can be replaced with
*(bPtr+3)
Or can be replaced with
*(b+3)
*bPtr+3
is equivalent to
b[0]+3
Example (Cont)
&b[3]
is equivalent to
bPtr+3
And is equiavalent to:
b+3
bPtr=&b[2];
cout<<*(bPtr+2); //prints b[4]
*(bPtr++); //increments bPtr
(*bPtr)++; //increments b[2]
Example: sum array
//using array notation
int sumArray(int X[100]){
int sum=0;
for (int i=0;i<=99;i++) sum+=X[i];
return sum;
}
//using pointer notation
int sumArray(int*X){
int *xptr;
int sum=0;
for (xptr=&X[0]; xptr<=&X[99]; xptr++) sum+=*xptr;
return sum;
}
Example: Find string length
//using array notation
int length(char X[ ]){
int c=0;
for (int i=0;X[i];i++) c++;
return c;
}
//using pointer notation
int length(char *X){
int c=0;
for (;*X;X++) c++;
return c;
}
Example: difference in cout between pointers to
characters and other pointers
int A[5]={7,5,3,1,8};
char B[]=”abcde”;
int *aptr=A+2;
char *bptr=B+2;
cout<<A; //FAB0
cout<<B; //abcde
cout<<*A;//7
cout<<*B;//a
cout<<aptr; //FAB4
cout<<bptr; //cde
cout<<*(aptr+1); //1
cout<<*(bptr+1);//d
cout<<*aptr+1;//4
cout<<bptr+1;//de
Strings using pointers
The declaration
char color[]=”blue”;
is equivalent to
char * colorPtr=”blue”; // creates a pointer variable colorPtr that points to the string
// “blue” somewhere in memory
color=”red”;
//compiler error
colorPtr=”red”;
//ok: First “red” is stored in memory then its address is stored in colorPtr
cout<<color;
//red
cout<<colorPtr;
//red
cin>>color;
//ok: reads characters into statically allocated memory
cin>>colorPtr;
//might cause run-time error: illegal mem access. cin tries to store string at
//the location currently pointed to by colorPtr.
colorPtr=new char[20];
cin>>colorPtr; //ok
char t;
colorPtr=&t;
cin>>*colorPtr //reads a single character and stores it in t
cout<<colorPtr; //prints the first character correctly followed by junk characters
const qulaifier
The const qualifier informs the compiler that the value of a
variable should not be modified once given a value.
char ch;
char *s=&ch; // a non constant pointer to non-constant data
const char *s=&ch; // a non constant pointer to constant data
char * const s=&ch; // a constant pointer to non-constant data
const char * const s=&ch; // a constant pointer to constant data
const qulaifier (Cont)
Non-constant pointer to no-constant data:
void convertToUpperCase (char *s){…}
Non-constant pointer to constant data:
void printString (const char *s){…}
constant pointer to no-constant data:
void convertFirstCharToUpper (char * const s){…}
constant pointer to constant data:
int stringLength (const char * const s){char *t=s; …}
Example
void copy1(char s1[], const char s2[]){
int i;
for(i=0;s1[i]=s2[i];i++);
}
void copy2(char *s1, const char *s2){
int i;
for(i=0;*s1=*s2;s1++,s2++);
}
void main(){
char A[10],*B=”hellow”, C[10], D[]=”good bye”;
copy1(A,B);
copy2(C,D);
cout<<A<<B<<C<<D;
}
Strings using pointers cont.
The following often results in a run-time error
(illegal memory access):
void f(char *s){(*s)++;}
void main( ){f(‘a’);}
main passes 97 to s which is the address of some
location that is often reserved for the os.
Strings using pointers cont.
Another way to store a list of names:
char *N[]={“ali”, “ahmad”,”sami”}; //draw the resulting memory
cout<<N[0]; //ali
cout<<N[0][1]//l
cout<<*(N[0]+2); //i
cout<<N[1]+1; //hmad
cin>>N[0];// ok only if string is shorter than 3 characters
Example: Given
char * N[50 ]={"ali", "ahmad", …};
Write a code segment to print the names in N.
for( int I=0; I <=49; I++ )
cout<<N[I];
Exercizes: Given
char * N[50 ]={"ali", "ahmad", …};
• write a code segment to count the names in N
starting with a.
• write a code segment to find the longest name
in N
Character handling library
The header file <ctype.h> includes prototypes of functions that
manipulate characters as integers. Some of these are:
int isdigit(int c)
int isalpha(int c)
int islower(int c)
int isupper(int c)
int toupper(int c)
…
Standard I/O library
• The header file <stdio.h> includes prototypes of functions
that perform I/O. Some of these are:
putchar(int c): prints a character to the screen
gets(char *s): inputs characters from the standard input
into the array s until a new line or EOF (ctrl+z) character is
encountered. A terminating NULL character is appended to
the array. gets allows reading a string that contains
characters
Example
#include <stdio.h>
void main(){
char sentence[80];
void reverse(char *);
gets(sentence);
reverse(sentence);
}
void reverse(char *s){
if (s[0]==’\0’)
return;
else{
reverse(&s[1]);
putchar(s[0]);
}
}
Standard I/O library (cont.)
int getchar():
takes the next character from the standard
input and return it as an integer.
puts(const char *s):
print the string s followed by new line
character.
String handling library
• The header file <string.h> includes prototypes of functions
that perform operations on strings. Some of these are:
int strlen(char * s):
returns the number of characters in the string. The NULL
character is not counted.
char *strcpy(char *s1,const char *s2):
copies the string s2 into s1. The value of s1 is returned.
Memory must be already allocated for s1 before the
function can be executed.
Example
char s1[10]=”abcd”;
char s2[]=”ef”;
char* s3=”12345678”;
char* s4;
strcpy(s1,s2); //error
strcpy(s2,s1);//ok
strcpy(s1,s3);// ok
strcpy(s3,s1);//ok
strcpy(s4,s3);//might be run-time error since s4 has no memory. It tries to copy s3
//to the location pointed to by s4.
strcpy(s4,”abc”); //might be run-time error since s4 has no memory. It tries to copy
//to location pointed to by s4.
strcpy(s3,”abc”);// ok
strcpy(s1,”abc”);// ok
strcpy(s2,”abc”); //error
strcpy(s4,”abc”); //error
strcpy(s1,s3+3); //ok
strcpy(s1+1,s3+3); //ok
cout<<s1;
cout<<s3;
Example: Given
char A[10]=…;
char B[10]= …;
Write a code segment to exhange A, B
//wrong attempt: compiler error
char T[10];
T=A;
A=B;
B=T;
//correct solution
char T[10];
strcpy(T,A);
strcpy(A,B);
strcpy(B,T);
Example: Given
char * A=…;
char * B= …;
Write a code segment to exhange A, B
//correct solution
char *T;
T=A;
A=B;
B=T;
//another correct solution
char T[10];
strcpy(T,A);
strcpy(A,B);
strcpy(B,T);
Example: Write a function to exchange 2 strings
//wrong attempt
void exchange(char *s1, char *s2){
char *T; T=A; A=B; B=T;
}
//correct solution
void exchange(char *s1, char *s2){
char T[10]; strcpy(T,A); strcpy(A,B); strcpy(B,T);
}
String handling library (cont.)
char *strcat(char *s1,const char *s2):
appends string s2 to array s1. The first character of
s2 replaces the terminating NULL character of s1.
The value of s1 is returned. Enough memory must
be already allocated for s1 before the function can
be executed.
Example
char s1[10]=”defg”;
char s2[10]=”ab”;
char* s3=”abc”;
char* s4;
strcat(s4,”abc”); //might be run-time error
strcat(“abc”,s4); //compiler error
strcat(s1,s2);//ok
strcat(s1,s3);//ok
strcat(s4,s3);//might cause run-time error
strcat(s3,s1); //might cause run-time error
String handling library (cont.)
int strcmp(const char *s1, const char *s2):
The function returns one of the following:
0 if the string s1 equals to the string s2.
-1 (or a negative integer) if the string s1 < the string s2.
+1 (or a positive integer) if the string s1 > the string s2.
Example
char s[10]=”ali”;
char t[20]=”ahmad”;
char *u=”ali”;
cout<<strcmp(s,t); //1
cout<<strcmp(t,s); //-1
cout<<strcmp(s,u); //0
Example: Given
char * N[50]={"sami", "ahmad", … };
Write a code segment to sort the names in N in alphabetical order
int i, j;
for(i=0;i<50;i++)
for(j=i+1; j<50; j++)
if (strcmp(N[i],N[j])==1){
//exchange N[i],N[j]
char T[20];
strcpy(T,N[i]);
strcpy(N[i],N[j]);
strcpy(N[j],T);
}
Exercize: Text Analysis
Write a program that reads several lines of text and outputs:
A table indicating the occurrence of each letter of the
alphabet in the text.
A table indicating the number of one-letter words, 2-letter
words, three letter words, … appearing in the text.
A table indicating the number of occurrences of each
different word in the text.