0% found this document useful (0 votes)
7 views52 pages

1.3 - Review Pointer

The document provides an overview of pointers in C programming, explaining how pointers store memory addresses and how to declare and use them. It covers the use of the & and * operators for obtaining addresses and dereferencing pointers, as well as examples of pointer operations and their significance in manipulating memory and function arguments. Additionally, it discusses the importance of initializing pointers and avoiding dereferencing null pointers.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views52 pages

1.3 - Review Pointer

The document provides an overview of pointers in C programming, explaining how pointers store memory addresses and how to declare and use them. It covers the use of the & and * operators for obtaining addresses and dereferencing pointers, as well as examples of pointer operations and their significance in manipulating memory and function arguments. Additionally, it discusses the importance of initializing pointers and avoiding dereferencing null pointers.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 52

Pointers in C

Dr. Tanvir Ahmed

1
Data and Memory
• If you remember whenever we declare a variable, it takes an space in
memory
• You can consider a memory like many rows and each row as 8 bit
capacity
• Each row has an address
• If we execute the line: char ch = 'A'
• and the variable ch happened to be stored in memory location 1000, our
picture would look like this:
• …….
1002
1001
1000 Binary of ascii of ‘A’
……
• An integer would be stored over 4 consecutive bytes, and the address of
the variable storing the integer would be the first memory address the
variable was stored in.
2
Pointers
• During the beginning of the semester while we
learned to declare a variable, we also saw how can
we print the address of a variable. We saw it in
Lecture 2 slide number 13:
– printf("Address of basic salary is %p\n", &basic_salary);
• If you declare an integer variable by:
– int x;
– You can use x to store an integer variable
– It has one address in the memory
– If you write x = 5, then 5 is stored in that block of memory.

3
Pointers
• Now, if you want to declare a variable that can store the
address of a variable, then you need a pointer.
• So, pointer is a type of variable, that can store address of
another variable
– While declaring a pointer,
• you have to specify the type of variable (int, float, char, etc.) while declaring a
pointer as different types of variables are stored differently.
– For example, char takes 1 byte, int takes 4 bytes (but one address!)

4
Declaring a Pointer
• So, pointer can hold a memory address.
• Pointer, points to a specific data type.
• Why specific data type? Because different type takes
different size in memory.
• Example of declaring a pointer:
int *p; //You have to put * before the variable
name. Like any uninitialized variable,
here p is pointing to a garbage address as it is not
initialized yet.
- Another example bellow:
int *pointer1 = &x; // Example of both declaration and
initialization in the same line

addr of x int x;

0x2000 1
0x9060
• The above statement also can be written as two lines
• int *pointer1;
• pointer1 = &x;

5
• A pointer has to be declared just like any other variable -
remember a pointer is just a variable that stores an
address. For example,
int *p;
• Here, p is a pointer to an integer. Adding an asterisk in
front of a variable's name declares it to be a pointer to
the declared type. Notice that the asterisk applies only
to the single variable name that it is in front of, so:
int *p , q;
- declares a pointer to an int and an int variable, NOT
two pointers.
The meaning of two new operators: &
and *
• The & operator returns the address of a
variable
For example:
int *p , q;
• declares p, a pointer to int, and q an int and
• The instruction: p=&q;
stores the address of q in p
p
q
addr of q
1
0x2000
0x9060
Operator *
• When you declare a pointer, you have to put *.
However, if you use * with a pointer any time after
declaring it, it has different meaning.
• If place * in front of a pointer variable then the result is
the value stored in the variable pointed at.
• That is, p stores the address, or pointer, to another
variable and *p is the value stored in the variable that p
points at.
• The * operator is called the de-referencing operator and
it helps not to confuse it with multiplication
De-referencing Example
Consider this few lines of codes bellow, It will
print 1: p
q
0x9060
int *p , q; 0x2000
1
0x9060
p=&q;
printf(“%d”, *p); //this will print the value of q
• Why it is printing the value of q?
– Because, we are de-referencing p by writing *p
– The *p in the printf means, the variable it is pointing to. As
p is pointing to q, *p means actually q.
– Now you know the differences between *p in the first line
and *p in the third line
9
Summary of using * and &
• To declare a pointer add an * in front of its
name.
• To obtain the address of a variable use & in
front of its name.
• To obtain the value of a variable use * in
front of a pointer's name.
Example of pointer operation
Now see if you can work out what the following
means:
int *a , b , c;
b = 10;
a = &b;
c = *a;
• Firstly three variables are declared:
– a (a pointer to int),
– and b and c (both standard integers).
• The instruction is a=&b which stores the address of b
in a
• Finally c = *a stores the value in the variable pointed
to by a in c.
– As a points to b, its value i.e. 1O is stored in c
int main() output:
{ Pointer example p1 = 0x7ffce97158f8
p2 = 0x7ffce97158fc
*p1 = -42
*p2 = 163
int x, y;
---------
int *p1, *p2;
p1 = 0x7ffce97158f8 *p1 = 17
x = -42;
---------
y=163;
p1 = 0x7ffce97158fc *p1 = 163
p1 = &x;
---------
p2 = &y; ---------
printf("p1 = %p *p1 = %d \n", p1, *p1); p2 = 0x7ffce97158f8 *p2 = 17
printf("p2 = %p *p2 = %d \n", p2, *p2); p1 = 0x7ffce97158fc *p1 = 17
printf("---------\n"); ---------

*p1 = 17; // dereferencing. It means put 17 to the address


where p1 is pointing to. Kind of x = 17
printf("p1 = %p *p1 = %d \n", p1, *p1);
printf("---------\n");

p1 = p2; //p1 is not pointing to x anymore. Now pointing to y


printf("p1 = %p *p1 = %d \n", p1, *p1);
printf("---------\n");

p2 = &x;
printf("---------\n");
printf("p2 = %p *p2 = %d \n", p2, *p2);

*p1 = *p2;
printf("p1 = %p *p1 = %d \n", p1, *p1);
printf("---------");
return 0;
12
}
Testing pointer is pointing
something meaningful
• If a pointer is not initialized to any address, dereferencing that pointer
might result in garbage value, or can create segmentation fault/run-
time error as your code is trying to access a memory which is not
allocated to your program. In that case we can use the following
technique to prevent such potential error.
• We can assign NULL to a pointer.
• int *aPtr = NULL;
• It's important not to dereference a null pointer. Doing so will lead to a run-time
error.
• However, before dereferencing we can check it is NULL or not:
– if (aPtr) //it checks if aPtr is not NULL.
{ write statements that can use aPtr as it is safe to do so}
• The above line checks if aPtr is NULL or not.
– You could also write: if (aPtr!= NULL) //this is same as if (aPtr)
• Note that it is programmer’s responsibility to assing NULL values when necessary
13
Why to use pointer
• C programming language WANTED the programmer to
have the ability to directly manipulate memory.

• Allow you to refer to a large data structure in a


compact way.
• To modify a variable in a function that is not a global,
or a local to that function
• To save time
• To use dynamic memory
• Pointer is used extensively in linked structures like
linked list, trees that you will learn in CS1 course if you
have to take it
14
Pointers and Function Arguments
• Call by value (We learned about it when we were
learning function)
• Call by reference
• Let’s say, we want to write a function that can take
two parameters and can swap their values.
• For example, x = 1 and y=2. After passing x and y to the swap
function, we want, x will become 2 and y will be came 1 for
the following example.

x: 1 x: 2
swap
y: 2 y: 1

15
#include <stdio.h>
Here is our Solution 1
void fakeSwap(int a, int b)
{
int tmp;

tmp = a;
a = b;
b = tmp;
}

int main()
{
int x = 1, y = 2;

fakeSwap(x, y);
printf(“%d %d\n”, x, y);
return 0;
}
16
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{
int tmp;

tmp = a;
a = b;
b = tmp;
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
17
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{ tmp:
int tmp; 0x2060

a:
tmp = a; 1 0x2038
a = b;
b:
b = tmp; 2 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
18
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = a; 1 0x2038
a = b;
b:
b = tmp; 2 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
19
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = a; 2 0x2038
a = b;
b:
b = tmp; 2 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
20
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = a; 2 0x2038
a = b;
b:
b = tmp; 1 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
21
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{
int tmp;

tmp = a;
a = b;
b = tmp;
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
22
#include <stdio.h>
Here is our Solution 2
void trueSwap(int* a, int* b)
{
int tmp;

tmp = *a;
*a = *b;
*b = tmp;
}

int main()
{
int x = 1, y = 2;

trueSwap(&x, &y);
printf(“%d %d\n”, x, y);
return 0;
}
23
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{
int tmp;

tmp = *a;
*a = *b;
*b = tmp;
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
24
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{ tmp:
int tmp; 0x2060

a:
tmp = *a; addr of x 0x2038
*a = *b;
b:
*b = tmp; addr of y 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
25
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = *a; addr of x 0x2038
*a = *b;
b:
*b = tmp; addr of y 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
26
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = *a; addr of x 0x2038
*a = *b;
b:
*b = tmp; addr of y 0x2040
}

int main()
{
int x = 1, y = 2;
x:
2 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
27
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = *a; addr of x 0x2038
*a = *b;
b:
*b = tmp; addr of y 0x2040
}

int main()
{
int x = 1, y = 2;
x:
2 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
1 0x2010
return 0;
}
28
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{ So, truSwap
int tmp;
managed to
swap x and y!
tmp = *a;
*a = *b;
*b = tmp;
}

int main()
{
int x = 1, y = 2;
x:
2 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
1 0x2010
return 0;
}
29
Call by value and call by reference example conclusion

• The first solution used call by value method.


– It just copied the values from x, y into a, b
respectively
– Change in a and b did not affect x and y
• The second solution used call by reference
– We used pointer a and be to hold the address of
x and y
– So in the function we actually changed the value
within the address of x and y.
– So after completing the function call, the value of
x and y have changed

30
Pointer of Pointer
• The concept of pointers can be further
extended.
• Pointer, we know is a variable that contains
address of another variable.
• Now this variable itself might be another
pointer.
• Thus, we now have a pointer that contains
another pointer’s address.
• The following example should make this point
clear.
31
int main( )
{
int i = 3, *j, **k ;
j = &i ;
k = &j ;// K has the capability to hold address of pointer
printf ( "\nAddress of i = %u", &i ) ; //print address of i
printf ( "\nAddress of i = %u", j ) ; //print address of i
printf ( "\nAddress of i = %u", *k ) ; //print address of i
printf ( "\nAddress of j = %u", &j ) ; //print address of j
printf ( "\nAddress of j = %u", k ) ; //print address of j
printf ( "\nAddress of k = %u", &k ) ; //print address of k
printf ( "\nValue of j = %u", j ) ; //print value of j, which is address of i
printf ( "\nValue of k = %u", k ) ; //print value of k, which is address of j
printf ( "\nValue of i = %d", i ) ; //print 3
printf ( "\nValue of i = %d", * ( &i ) ) ; //print 3
printf ( "\nValue of i = %d", *j ) ; //print print 3
printf ( "\nValue of i = %d", **k ) ; //print 3. As *k = j, and *j = i, i=3
return 0;
}
//output:
Address of i = 178371580
Address of i = 178371580 i j k
Address of i = 178371580
Address of j = 178371584 178371580 178371584
Address of j = 178371584 3
Address of k = 178371592
Value of j = 178371580 178371580 178371584 178371592
Value of k = 178371584
Value of i = 3
Value of i = 3
Value of i = 3 32
Value of i = 3
Pointers and Arrays
int array[size];
int* pPtr = array + i; //let’s say i is an index of the array

int* qPtr = array + j; //let’s say j is an index of the array

▪ The name array is equivalent to &array[0]


▪ It means, name of an array is a pointer
▪ pPtr++ increments pPtr to point to the next element
of array.
▪ pPtr += n increments pPtr to point to n elements
beyond where it currently points.
▪ pPtr-qPtr equals i-j.
▪ Thus, we can see that a pointer arithmetic depends
on the type.
▪ The increment or decrement will jump to 4 bytes if
the pointer is integer pointer. 33
Pointers and Arrays (cont)
A normal 1 dimensional array:
Type array[size];

▪ array[0] is equivalent to *array


▪ array[n] is equivalent to *(array + n)

34
Basic Pointer Arithmetic
0x2008 0x200C 0x2010 0x2014 0x2018
array:

0x2008

0 1 2 3 4

pPtr: qPtr:

0x2004 0x2008 0x2000 NULL

float array[5];
float* pPtr = array;
float* qPtr = NULL;

35
0x2008 0x200C 0x2010 0x2014 0x2018
array:

0x2008

0 1 2 3 4

pPtr: qPtr:

0x2004 0x200C 0x2000 NULL

float array[5];
float* pPtr = array;
float* qPtr = NULL;

pPtr++; /* pPtr now holds the address: &array[1] */

36
0x2008 0x200C 0x2010 0x2014 0x2018
array:

0x2008

0 1 2 3 4

pPtr: qPtr:

0x2004 0x2018 0x2000 NULL

float array[5];
float* pPtr = array;
float* qPtr = NULL;

pPtr++; /* pPtr = &array[1] */


pPtr += 3; /* pPtr now hold the address: &array[4] */

37
0x2008 0x200C 0x2010 0x2014 0x2018
array:

0x2008

0 1 2 3 4

pPtr: qPtr:

0x2004 0x2018 0x2000 0x2010

float array[5];
float* pPtr = array;
float* qPtr = NULL;

pPtr++; /* pPtr = &array[1] */


pPtr += 3; /* pPtr = &array[4] */
qPtr = array + 2; /*qPtr now holds the address &array[2]*/
38
0x2008 0x200C 0x2010 0x2014 0x2018
array:

0x2008

0 1 2 3 4

pPtr: qPtr:

0x2004 0x2018 0x2000 0x2010

float array[5];
float* pPtr = array;
float* qPtr = NULL;

pPtr++; /* pPtr = &array[1] */


pPtr += 3; /* pPtr = &array[4] */
qPtr = array + 2; /* qPtr = &array[2] */
printf(“%d\n”, pPtr-qPtr);
39
int main() Example: traversing through array using pointer
{
int data[] = {87, 99, 75, 88, 93};
int *p;
int i;
for(i = 0; i<5; i++)
printf("address: %p, value: %d, test: %d\n", data+i,
*(data+i), *data+i);

printf("--------using p-------------\n");
p = data; // p is now &data[0]
for(i = 0; i<5; i++)
{
printf("address: %p, value: %d \n", p, *p);
p++;
} output:
address: 0x7ffd8ec91e10, value: 87, test: 87
address: 0x7ffd8ec91e14, value: 99, test: 88
return 0; address: 0x7ffd8ec91e18, value: 75, test: 89
} address: 0x7ffd8ec91e1c, value: 88, test: 90
The values of address: 0x7ffd8ec91e20, value: 93, test: 91
the array also --------using p-------------
address: 0x7ffd8ec91e10, value: 87 It is just adding i to
can be accessed data[0].
using: address: 0x7ffd8ec91e14, value: 99
address: 0x7ffd8ec91e18, value: 75 *data is dereferencing
data[i] data (which is &data[0])
*(i+data) address: 0x7ffd8ec91e1c, value: 88
40
i[data] address: 0x7ffd8ec91e20, value: 93
What is the difference between
pointer and array?
• While double values[10]; allocates 10
locations to store doubles, double *p; does
not.
• Instead double *p; only allocates the
memory to store a single location in memory.
• However, we CAN use a pointer to
dynamically allocate memory, that we will
learn later in the semester (if we get time).

41
Passing Entire Array to Function
main( )
{
int num[ ] = { 24, 34, 12, 44, 56, 17 } ;
int i;
printf("Original Array: ");
for(i=0; i<6; i++)
printf("%d ", num[i]);

incBy2( num, 6 ) ;

printf("\nArray after calling incBy2: ");


for(i=0; i<6; i++)
printf("%d ", num[i]);
}
void incBy2(int *A, int n)//also can be written as: incBy2(int A[], int n) or incBy2(int A[6], int n)
{
int i ;
for ( i = 0 ; i < n ; i++ )
{
*A = *A + 2; //in crease an a particular array element by 2
A++; //A is jumping to the next array element’s address
}
} Output:
Original Array: 24 34 12 44 56 17
Array after calling incBy2: 26 36 14 46 58 19 42
Another version-Passing Entire Array to Function
main( )
{
int num[ ] = { 24, 34, 12, 44, 56, 17 } ;
int i;
printf("Original Array: ");
for(i=0; i<6; i++)
printf("%d ", num[i]);

incBy2( num, 6 ) ;

printf("\nArray after calling incBy2: ");


for(i=0; i<6; i++)
printf("%d ", num[i]);
}
void incBy2(int *A, int n)//also can be written as: incBy2(int A[], int n) or incBy2(int A[6], int n)
{
int i ;
for ( i = 0 ; i < n ; i++ )
{
//even A is a pointer, you can write it like an array as you have passed an array here
A[i] = A[i] + 2;
Output:
} Original Array: 24 34 12 44 56 17
} Array after calling incBy2: 26 36 14 46 58 19
43
Multidimensional Arrays and Pointers
• As we have discussed in another lecture and 2D
array, an example declaration is :
• int grid[4][2];
• This array as 4 rows and 2 columns. Can be seen as:

Colum 0 Column 1
Row 0 grid[0][0] grid[0][1]
Row 1 grid[1][0] grid[1][1]
Row 2 grid[2][0] grid[2][1]
Row 3 grid[3][0] grid[3][1]

44
Multidimensional Arrays with Pointers
• The declaration int grid[4][2]; can also be
interpreted as:
• This is an array of 4 elements
– Each element is an array of 2 elements
• So, it is kind of 4 one-dimensional arrays.
• Example: grid[0] is an array of 2 elements
– grid[0][0], and grid[0][1]
• The elements are laid out sequentially in
memory, just like a one-dimensional array

45
Multidimensional Arrays
Index grid[0][0] grid[0][1] grid[1][0] grid[1][1] grid[2][0] grid[2][1] grid[3][0] grid[3][1]

Value 5 6 8 23 22 9 90 4
address 1000 1004 1008 1012 1016 1020 1024 1028

• The above table shows the memory map for the


2D array we have declared. The address and
data are assumed. We consider int takes 4
bytes.
• See, grid[1][0] starts after completing full
grid[0] array.

46
2D Array is an array of array
main( )
{
int grid[4][2] = {
{ 5, 6 },
{ 8, 23 },
{ 22, 9 },
{ 90, 4 }
} ;
int i ;
for ( i = 0 ; i <= 3 ; i++ )
printf ( "\nAddress of %d th 1-D array = %u", i, grid[i] ) ;
}

Output:
Address of 0 th 1-D array = 2961709872
Address of 1 th 1-D array = 2961709880
Address of 2 th 1-D array = 2961709888
Address of 3 th 1-D array = 2961709896

See, it is printing address of each row


47
Accessing 2D array using pointer
• The following are equivalent:
• s[2][1] //second row, first col
• *(s[2]+1)
• *(*(s+2)+1) //here 2 indicates
the array number

48
Accessing 2D array using pointer
main( )
{
int s[4][2] = {
{ 5, 6 },
{ 8, 23 },
{ 22, 9 },
{ 90, 4 }
} ;
int i, j ;
for ( i = 0 ; i <= 3 ; i++ )
{
printf ( "\n" ) ;
for ( j = 0 ; j <= 1 ; j++ )
printf ( "%d ", *( *( s + i ) + j ) ) ;
}
}

Output:
5 6
8 23
22 9
90 4

49
2D array as parameter
• Only first subscript may be left unspecified
• void f1(int grid[][10]) // valid
• void f3(int grid[][]); //invalid
• Generally, array sizes are also passed to functions while
dealing with 1D or multi dimensional array
• void print( int a[ ][4], int row, int col )
• The sizes allow to iterate properly and access the elements
within the ranges.

50
main( )
Accessing 2D array using pointer
{ print ( int q[ ][4], int row, int col )
int a[3][4] = { {
1, 2, 3, 4, int i, j ;
5, 6, 7, 8, for ( i = 0 ; i < row ; i++ )
9, 0, 1, 6 {
} ; for ( j = 0 ; j < col ; j++ )
printf ( "%d ", q[i][j] ) ;
display ( a, 3, 4 ) ; printf ( "\n" ) ;
print ( a, 3, 4 ) ; }
} printf ( "\n" ) ;
}
display ( int *q, int row, int col )
{
int i, j ;
for ( i = 0 ; i < row ; i++ )
{
for ( j = 0 ; j < col ; j++ )
printf("%d ",*(q+i*col+j));
printf ( "\n" ) ;
}
printf ("\n" ) ;
}

51
52

You might also like