Pointers
Pointers
When you declare a variable in C, you are actually putting aside a portion of the
computer’s memory and labeling it with the variable name
The amount of memory that is used depends on the type of the variable: an int is
4 bytes, a char is 1 byte, a double is 8 bytes.
The location in memory is the memory address of the variable
For example, the declaration int x; results in 4 bytes of memory being put aside for
an integer
x
When you assign to the variable, you are storing a value in the memory at that address.
For example, x=5; results in
x
5
Normally a variable name in an expression stands for the value of that variable. For
example, x=x+4; should be read “set the value of x to be the old value of x plus 4”
When the & operator is placed before the name of a variable, the address-of operator
returns the memory address of the variable/operand.
For example, cout<<&x; we will not get the value stored by the variable, we get the
address of that variable, where it actually stores the data.
A pointer is a type of variable, special for holding the address of some other variable. In
the earlier example we retrieved the address of the ‘x’ variable by using ‘&x’. Now we
can store it in this special type of variable, the pointer.
We say that a pointer p “points” to a variable x if its value is the address of x.
To set the pointer p to point to the integer variable x, set the value of the pointer variable
p to be the address of x, p=&x;
x
p 5
1
Let’s see an example:
double i=6;
double*p; // p is a pointer to double
// p must hold a memory address of a double
i
6 p
To set a pointer to point to nothing, set it to the reserved value NULL or, alternatively, to
the value 0
P=NULL; or p=0;
Assume pointer p is a pointer pointing to variable i. We use the * operator (called the
dereferencing operator) to access i from p.
The expression *p can be read ”the value at the memory location pointed to by p”.
cout<<*p; is the same as cout<<i;
Example,
int y=5; y
60000 5
2
To set the pointer yptr to point to the variable y
yptr = &y; // yptr points to y
//yptr holds the address of y
yptr y
50000 60000 60000 5
y
5
yPtr
cout<<&y; //60000
cout<<yptr; //60000
We can access the content of the variable y using its pointer yptr
cout<<*yptr; //5
Examples,
int *w; //w is a pointer to int t
int t=5; 5
w=&t; //w points to t w
cout<<t; //5
cout<<*w; //5 t
6
t++; //t = 6 w
cout<<*w; //6
t
*w=*w+2; //*w is 8 8
cout<<*w; //8 w
cout<<t; //8
cout<<&t; // 0012FF78
cout<<w; //0012FF78
//The address displayed may be any address in memory. But it will be the same
for w or &t.
//* and & are inverses (they cancel each other out)
cout<<&*w; // 0012FF78
cout<<*&w; // 0012FF78
Example,
float r; int *w; //w is a pointer to int
w=&r; //syntax error
*w=5; //compiler error
Note: if several pointers are declared in the same line, each must be proceeded by a *:
int *w,*p,*z; //w is a pointer to int
3
Pointers Assignment/Comparison
Assignment /comparison to other pointers of the same type is valid
pointer1=pointer2 is valid, address is copied from pointer2 to pointer1, that
is both pointers points to the same value.
pointer1<pointer2, pointer1>pointer2, pointer1==pointer2 is valid, the
result is true or false.
Assignment /comparison to the value 0 ONLY is allowed pointer = =0,
pointer=0 is valid.
Example,
int i=2;
double j=3;
int *ip=&i;
double *jp=&j;
ip=jp; //syntax error
if(ip= =jp) //syntax error
ip=3000; //Error
Example,
int i=2;
int j=3;
int *ip=&i;
int *jp=&j;
0x002000 2 i
:
0x002008 3 j
:
0x002012 0x002000 ip
:
0x002020 0x002008 jp
4
Example, given:
int a=3;
int b=8;
int c=12;
int *ap=&a;
int *bp=&b;
int *cp=&c;
ap=bp;
*bp=*cp
Which of the following evaluates to true?
b= =c? //true
bp= =cp? //false
*ap= =c? //true
When we add an integer value to a pointer, the pointer is not simply incremented by
the value of the integer, but by that integer times the size of the object to which the
pointer refers.
New Address = Old Address + (integer * size of object)
5
When we subtract an integer value from a pointer, the pointer is not simply
decremented by the value of the integer, but by that integer times the size of the
object to which the pointer refers.
New Address = Old Address - (integer * size of object)
int A[]={2,4,6,8,10};
The array name A is a constant pointer to A[0]
The array name A is the same as &A[0]
Example,
if (A = =&A[0]) {…} //is always true
int x=5;
A=&x; // error
A++; // error
int *p = &A[0];
or
int *p = A;
6
e.g.1, Given: sizeof (int)=4 bytes.
int A[]={2,4,6,8,10};
int *p = A; or int *p=&A[0];
What the output of each of the following?
cout<<(p+0); //3000
cout<<(p+1); //3004
cout<<(p+2); //3008
cout<<(p+3); //3012
cout<<(p+4); //3016
cout<<*(p+0); //A[0]
cout<<*(p+1); //A[1]
cout<<*(p+2); //A[2]
cout<<*(p+3); //A[3]
cout<<*(p+4); //A[4]
cout<<*(A+0); //A[0]
cout<<*(A+1); //A[1]
cout<<*(A+2); //A[2]
cout<<*(A+3); //A[3]
cout<<*(A+4); //A[4]
7
e.g.2,
Given:
int b[5]={12,7,4,11,16};
int* bPtr=b;
What is the output of each of the following?
cout<<b[3]; //11
cout<<*(bPtr+3); //11
cout<<*(b+3); //11
cout<<*b+3; //15
cout<<*bPtr+3; //15
cout<<b[0]+3; //15
bPtr=&b[2];
cout<<*(bPtr+2); //prints b[4]
e.g.3,
Given:
int x[]={6,9,2,3,5};
int *P = x+2;
6 9 2 3 5
p following?
What is the output of each of the
cout<<*(P + 2); //5
cout<<*P; //2
P+=2;
cout<<*P; //5
cout<<*(P - 2); //2
cout<<*P; //5
P-=2;
cout<<*P; //2
cout<<++(*P); //3
cout<<(*P)++; //3
cout<<*P; //4
cout<<*++P<<endl; //3
cout<<*P<<endl; //3
cout<<*P++<<endl; //3
cout<<*P<<endl; //5
8
e.g.4, Given:
int a[10]={3,9,2,4,5,1,2,4,9,10};
int *p; int*Q;
What the output of each of the following?
p=&a[4];
Q=p+3;
*(Q-3)=*Q;
int x=Q-p;
cout<<x; //3
cout<<*(Q-1)-*(p+1); //1
p=*(Q-2)+Q;
cout<<*p; //9
e.g.5, Given:
int a[]={2,4,1,3,2,1,6};
int*p=a+5;
What the output of each of the following?
p--;
cout<<*p<<endl; //2
cout<<*--p<<endl; //3
cout<<++*++p<<endl; //3
cout<<++*p++<<endl; //4
cout<<*p<<endl; //1
e.g.6, declare and initialize an array of 10 floats then do the following using pointer
notation:
Find the average of the elements
Find the min/max of the elements
float a[10];float*p=a;
for(int i=0;i<10;i++){cin>>*p;p++;}
p=a;
float max=*p,min=*p,sum=0;
for(i=0;i<10;i++){
sum+=*p;
if(*p>max)max=*p;
if(*p<min)min=*p;
p++;
}
cout<<min<<" "<<max<<endl;
cout<<(sum/(p-a))<<endl;
9
e.g.7, declare and initialize an array of 10 doubles then do the following using pointer
notation:
Print each one cell and skip the next
Swap each 2 adjacent cells
double a[10];double*p=a;
for(int i=0;i<10;i++){cin>>*p;p++;}
p=a;
for(i=0;i<10;i+=2){
cout<<*p;
p+=2;}
p=a; double t;
for(i=0;i<10;i+=2){
t=*p;
*p=*(p+1);
*(p+1)=t;
p+=2;}
p=a;
for( i=0;i<10;i++){cout<<*p<<endl;p++;}
e.g.8, Given
int a[]={3,9,-2,4,5,20,15,14};
Sort the array in ascending order using pointer notation. Then find min/max
int*p=a;
for(int i=0;i<8;i++){
for(int j=i+1;j<8;j++){
if(*(p+i)>*(p+j)){
int t=*(p+i);
*(p+i)=*(p+j);
*(p+j)=t;
}
}
}
cout<<"min = "<<*p<<endl;
cout<<"max = "<<*(p+7)<<endl;
10
The difference between pointers to characters and other pointers
Examples,
cout<<x[1]; //2
cout<<*(x+1); //2
cout<<*(xp+1); //2
-----------------------------------------------------------
char c[] = "hello";
char *cp = c; //or char *cp = ”hello”;
cout<<c; //hello
cout<<cp; //hello
cout<< &c[0]; //hello
cout<<c+1; //ello
cout<<cp+1; //ello
cout<<&c[1]; //ello
cout<<c[1]; //e
cout<<*(cp+1); //e
cout<<*(c+1); //e
-----------------------------------------------------------
NOTES:
int *xp=x;
//cin>>xp; //compiler error
-----------------------------------------------------------
char c[10];
cin>>c; //will not produce an error
//because c contains a valid address
//string length 9
11
char c[]=”hello”;
cin>>c; //will not produce an error
//because c contains a valid address
//string length 5
-----------------------------------------------------------
char c[10];
char *cp=c;
cin>>cp; //will not produce an error
//because cp contains a valid address
//string length 9
-----------------------------------------------------------
char c[]=”hello”;
char *cp=c;
cin>>cp; //will not produce an error
//because cp contains a valid address
//string length 5
-----------------------------------------------------------
char *cp;
//cin>>*cp; //run-time error because cp does not
contain //a valid address
Examples,
e.g.1:
int A[5]={7,5,3,1,8};
char B[]=”abcde”;
int *aptr=A+2;
char *bptr=B+2;
cout<<A; // address of element 0
cout<<B; // abcde
cout<<*A; //7
cout<<*B; //a
cout<<aptr; //address of element 2
cout<<bptr; //cde
cout<<*(aptr+1); //1
cout<<*(bptr+1); //d
cout<<*aptr+1; //4
cout<<bptr+1; //de
e.g.2: Given
char c[] = "hello";
char *sp ;
Print each character of a string on a separate line using pointer notation
for (int i=0;*(c+i)!=’\0’;i++)
cout << *(c+i) << endl;
or
for (sp=c ; *sp!='\0'; sp++)
cout << *sp <<endl;
12
e.g.3: given a string convert it to upper case using pointer notation
char s[200];
char *sp=s;
cin>>s; //or cin>>sp;
for(;*sp;sp++){if(*sp>='a'&& *sp<='z')*sp-=32;}
cout<<s; //or sp=s; cout<<sp;
//what is the output of the following?
cout<<sp-s; //the length of the string
e.g.1,
double z[2][2]={{5,6},{3,4}};
cout<<*s<<endl; //ali
cout<<**s<<endl; //a
cout<<*(*s+2)<<endl; //i
cout<<*s+1<<endl; //li
cout<<*(s+1)<<endl; //muna
cout<<**(s+1)<<endl; //m
cout<<*(*(s+1)+1)<<endl; //u
cout<<*(s+1)+1<<endl; //una
13
e.g.3, Given,
int x[2][3]={1,2,3,4,5,7};
Write a code segment to count even numbers. Do not use [].
int c=0;
for(int i=0;i<2;i++){
for(int j=0;j<3;j++){
if(*(*(x+i)+j)%2==0)c++;
}
}
cout<<c;
e.g.4, Given,
char s[2][80]={"ali","muna"};
Write a code segment to capitalize the names. Do not use [].
for(int i=0;i<2;i++){
for(int j=0;*(*(s+i)+j);j++){
if(*(*(s+i)+j)>='a' && *(*(s+i)+j)<='z')
*(*(s+i)+j)-=32;
}
}
for(int i=0;i<2;i++){
cout<<*(s+i);
}
e.g.1:
void square(int *x){*x =(*x)*(*x);}
void main(){int n=10;
square(&n);
cout<<n; //100
}
The address of n is copied in the pointer x, the function will operate on the original
argument n.
main() square(int*x)
Implied meaning
int *x=&n;
int n=10; *x=(*x)*(*x);
square(&n);
Points to
n x
10 &n
C++ style of Pass-by-reference
14
In the C style we have seen that you need to make use of & and lots of * symbols
to pass by reference.
In C++ we make use of the ‘reference parameter’ (or reference variable) and can
avoid the use of so many symbols. All what you need to do is to put & before
your function’s parameter.
e.g.1 (revisited),
void square(int &x){x=x*x;}
void main(){int n=10;
square(n);
cout<<n; //100
}
The function will operate on the original argument n.
e.g.2:
Write a code segment to get two numbers from the user and swap their values using a
function. The changes must be reflected in memory.
void swap1(int &x, int &y) { int temp=x;x=y;y=temp; }
void swap2(int *x, int *y) {int temp=*x;*x=*y;*y=temp;}
void main(){
int x=2,y=3;
swap1(x,y);
cout<<x<<y; //3 2
swap2(&x,&y);
cout<<x<<y; //2 3
}
e.g.3: Write a function to find the length of a string using pointer notation
int length(char *X){
int c=0;
for ( ; *X!=’\0’; X++) c++;
return c;
}
void main(){
char s1=”ali”; char *s2=”muna”;
cout<<length(s1);
cout<<length(s2);}
e.g.4: Write a function to copy a string to another string using pointer notation
void copy(char*p1,char*p2){
for(;*p2;p1++,p2++){*p1=*p2;}
*p1='\0';}
void main(){
char s[200];
char *sp="sami";
copy(s,sp);
cout<<s;}
e.g.5: Write a function to concatenate two strings using pointer notation
15
void con(char*p1,char*p2){
for(;*p1;p1++);
for(;*p2;p2++,p1++){*p1=*p2;}
*p1='\0';
}
void main(){
char s[200]="he";
char *sp="llo";
con(s,sp);
cout<<s;}
16
– Nonconstant pointer to nonconstant data
– Nonconstant pointer to constant data
– Constant pointer to nonconstant data
– Constant pointer to constant data
int x=5;
int y=6;
int *p=&x;
cout<<*p; //5
p=&y;
cout<<*p; //6
*p=7;
cout<<*p; //7
int x=5;
int y=6;
const int *p=&x;
cout<<*p; //5
p=&y;
cout<<*p; //6
*p=7; //error
int x=5;
int y=6;
int *const p=&x;
cout<<*p; //5
p=&y; //error
*p=7;
cout<<*p; //7
int x=5;
int y=6;
const int *const p=&x;
cout<<*p; //5
p=&y; //error
*p=7; //error
17
– int strlen( const char *s )
• Returns number of characters in string (null is not included in length)
e.g.1,
char s1[10] = "ali";
char *s2= "ahmad";
char *s3=”ali”;
18
char L[100]="hi ; how ,are;; you";
char*p=strtok(L," ,;\t\n");
while(p){
cout<<p<<endl;
p=strtok(NULL," ,;\t\n");
}
cout<<L; ??????
puts(char *s)
print the string s followed by new line character
int putchar(int c)
prints a character to the screen and returns it as an integer
int getchar()
takes the next character from the standard input and return it as an integer.
Examples,
e.g.1:
char sentence[80];
puts("Enter a line of text: ");
//cout<<"Enter a line of text: "<<endl;
gets(sentence); // until a new line
puts(sentence); // print the string
e.g.2:
Read a string char by char from KB
char ch;
char name[80];
int j=0;
ch=getchar();
while (ch!='\n'){
name[j]=ch;
j++;
ch=getchar();
}
name[j]=’\0’;
for(i=0;i<j;i++){
putchar (name[i]);
}
Character Handling Library (#include<ctype.h>)
19
int isdigit(int c) – returns true if c is a digit and false (0) otherwise
int isalpha(int c) – returns true if c is a letter and false (0) otherwise
int islower(int c) – returns true if c is lower case and false otherwise
int isupper(int c) – returns true if c is upper case and false otherwise
int toupper(int c) – returns corresponding uppercase character if original character
is lowercase; otherwise toupper returns original (uppercase) character
Example,
char p [] =“ABC123abc";
for(int j=0;j<strlen(p);j++){
if ( isupper(p[j]) ){ p[j] = tolower( p[j] ;}
//if ( isdigit(p[j]) ) cout<<p[j]; //123
//if ( isalpha(p[j]) ) cout<<p[j]; //abcabc
}
Array of Pointers
e.g.1,
int a=20,b=200,c=4,d=5;
int*p[4]={&a,&b,&c,&d};
/* or int*p[4];
p[0]=&a; p[1]=&b; p[2]=&c; p[3]=&d;*/
for(int i=0;i<4;i++){
cout<<p[i]<<endl;
//cout<<*(p+i)<<endl; }
for(i=0;i<4;i++){
cout<<*p[i]<<endl;
//cout<<*(*(p+i))<<endl; }
e.g.2,
//a list of names each of different size
char *N[2]={"ali", "ahmad"};
20
e.g.3: Given
char * N[3 ]={"alia", "ahmad", “sami”};
what is the output?
cout<<*N<<endl; //alia
cout<<*(N+1)<<endl; //ahmad
cout<<N[1]<<endl; //ahmad
cout<<*(N+1)+2<<endl; //mad
cout<<*N+2<<endl; //ia
cout<<*(*(N+2)+2); //m
cout<<*N[2]; //s
cout<<**N; //a
cout<<**(N+1); //a
Note:
char *p[3];
for(int i=0;i<3;i++) cin>>p[i]; //run-time error.
//Invalid address
e.g.4: Given
char * N[3 ]={"alia", "ahmad", “sami”};
write a code segment to count the names in N starting and ending with letter 'a'
int count=0;
for (int i=0;i<3;i++){
for(int j=0;*(N[i]+j);j++);
if(*(N[i]+0)==‘a’ && *(N[i]+j-1)=='a') count++;
//if(*(*(N+i)+0)==‘a’ && *(*(N+i)+j-1)=='a') count++;
//if (N[i][0]=='a' && N[i][j-1]=='a') count++;
e.g.5: Given
char * N[3 ]={"ali", "ahmad", “sami”};
write a code segment to find the longest name in N
int max,L=0;
for(int j=0;*(N[0]+j);j++);
max=j;
for (int i=1;i<3;i++){
for(j=0; *(N[i]+j);j++);
if (j>max) {max=j; l=i;}
}
cout<<N[L];
21
Pointers to pointers
e.g.1:
int a=5;
int*p1=&a;
int**p2=&p1;
cout<<a<<*p1<<**p2;
cout<<&a<<p1<<*p2;
e.g.2:
int a=2,c=3;
int*ap1=&a;
int**ap2=&ap1;
int *cp1=&c;
int**cp2=&cp1;
cout<<a<<*ap1<<**ap2<<endl;
cout<<&a<<ap1<<*ap2<<endl;
cout<<c<<*cp1<<**cp2<<endl;
cout<<&c<<cp1<<*cp2<<endl;
**ap2=*cp1+a;
cout<<**ap2<<endl; //5
cout<<*ap1<<endl; //5
cout<<a<<endl; //5
*ap2=cp1;
cout<<**ap2<<endl; //3
cout<<*ap1<<endl; //3
cout<<c<<endl; //3
22
Dynamic memory allocation
Declaration is used to statically allocate memory
The new operator is used to dynamically allocate memory
int *p;
p
60000 ?????
p=new int;
p
60000 50000
50000
7
:
p=’\0’;
p
23
60000 00000
50000
?
:
Example,
int *p=new int(30); //allocates memory and puts an initial value 30
p
4000 6000
6000 30
:
p=new int;
cin>>*P; //user entered 5
p
400 8000
Leaked memory
6000 30
:
8000 5
int *p;
24
p
60000 ?????
p=new int[2];
p
60000 50004
50004
50008 1
2
50004 ?
50008 ?
P=’\0’;
p
60000 00000
50004 ?
50008 ?
Note:
Declaring arrays dynamically allows us to choose their size while program is
running
int n;
cin>>n;
25
int *p;
p=new int[n]; //n does not need to be constant
for(int i=0;i<n;i++)cin>>*(p+i);
delete [] p;
p=’\0’;
e.g.1: declare and initialize a dynamic array of 10 integers. Find the sum of the array
elements.
int *p;
p=new int[10];
int sum=0;
for(int i=0;i<10;i++){cin>>*(p+i);sum+=*(p+i);}
delete [] p; p=’\0’;
Another solution:
int *p;
p=new int[10];
int*M=p;
int sum=0;
for(int i=0;i<10;i++){cin>>*M;sum+=*M;M++;}
delete [] p; p=’\0’; //or M=p; delete [] M; M='\0';
e.g.2:
Given
char*a[2]={"ali","muna"};
Write a code segment to concatenate the two strings in one string. You must do the
following:
1. find the length of the resulting string,
2. allocate memory dynamically for it
3. then copy the strings a[0] then a[1] into it
int len=0;
for(int i=0;i<2;i++){
for(int j=0;*(a[i]+j);j++);
len+=j;
}
char*p; int k=0;
p=new char[len+1];
for(i=0;i<2;i++){
for(int j=0;*(a[i]+j);j++){
*(p+k)= *(a[i]+j);
k++;
}
}
*(p+k)='\0';
26
cout<<p;
delete [] p;
p='\0';
Matrices:
e.g.1:
Store rows x cols matrix of integers in a dynamic matrix
int rows,cols; cin>>rows>>cols;
int **p;
p=new int*[rows];
p
P+1
: :
P+rows-1
for(int i=0;i<rows;i++){
*(p+i)=new int[cols];}
p *P
P+1 *(p+1) 0 … Cols-1
0 … Cols-1
: :
P+rows-1
*(P+rows-1) //to initialize the
0 … Cols-1
matrix from KB
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
cin>>*(*(p+i)+j);}}
for( i=0;i<rows;i++){
delete [] *(p+i);}
delete [] p;
p=’\0’;
e.g.2:
Write a code segment to allow the user to enter the scores of n students. The number of
scores of each student must be entered by the user.
cout<<"enter of number of students"<<endl;
int n; cin>>n;
int**p;
p=new int*[n];
27
for(int i=0;i<n;i++){
cout<<"enter of number scores for student "<<i<<endl;
int m; cin>>m;
*(p+i)=new int[m];
for(int j=0;j<m;j++){
cin>>*(*(p+i)+j); }
}
for(int j=0;j<n;j++)
delete []*(p+j);
delete [] p;
p='\0';
e.g.3:
Write a code segment to allow the user to enter N strings. Then save the strings in a
dynamic matrix and sort them alphabetically in ascending order (a…z).
int N;cin>>N;
char s[80];
char **p;
p=new char*[N];
for(int i=0;i<N;i++){
cin>>s;
*(p+i)=new char[strlen(s)+1];
strcpy(*(p+i),s);
}
for(i=0;i<N;i++){
for(j=i+1;j<N;j++){
if(strcmp(*(p+i),*(p+j))== 1 ){
char*t=*(p+i);
*(p+i)=*(p+j);
*(p+j)=t;
}}}
for(i=0;i<N;i++)cout<<*(p+i)<<endl;
for( i=0;i<N;i++){
delete [] *(p+i);
}delete [] p; p=’\0’;
28