Вы находитесь на странице: 1из 50

Pointers in C

Anurag Rana
What is a pointer?
A pointer is a variable whose value is the address of
another variable.

image courtesy - thegeekstuff.com


What is a pointer?
//variable declaration
Dereferencing a pointer
int var=5;
//pointer declaration indirection operator *
int *ptr;
//pointer initialization printf("%p\n",*ptr);
ptr = &var;
What is a pointer?
*ptr = &var; - incorrect, error/warning
int *ptr;
int * ptr;
int* ptr;
int*ptr;

image courtesy - thegeekstuff.com


Double Pointer
A pointer stores the address of a normal variable.
A double pointer stores the address of a pointer variable.

image courtesy - thegeekstuff.com


Double Pointer
Similarly there can be triple pointers and so on. until..
Why pointers ?
Fast and efficient code
Providing a convenient means for addressing many
types of problems
Dynamic memory allocation
Making expressions compact and succinct
Providing the ability to pass data structures by pointer
and many more..
Why pointers ?
So basically, C programming means pointers...
Problem with pointers
Problem with pointers
Accessing arrays and other data structures beyond
their bounds.
Referencing automatic variables after they have gone
out of existence.
Referencing heap allocated memory after it has been
released
Dereferencing a pointer before memory has been
allocated to it.
Memory
C program, when compiled use these type of memories.
How to read a declaration
const int *ptr;

ptr is a variable name/ is a variable.


ptr is a pointer variable.
ptr is a pointer variable to integer
ptr is a pointer variable to constant integer.

Read it ---- const int * const ptr;


Difference ?
const int * ptr VS int * const ptr VS int const * ptr?

int var1 = 0; int var1 = 0, var2 = 0;


const int* ptr = &var1; int *const ptr = &var1;
*ptr = 1; ptr = &var2;
printf("%d\n", *ptr); printf("%d\n", *ptr);
Good practices
Initialize pointers as soon as declared.
Print pointer address using %p field specifier.
%p print the complete hexadecimal address unlike %x
which print partial hexadecimal address (GCC 4.8.2, Ubuntu
14.08).

To make sure displaying pointer values on different


platforms do not cause any problem, cast the pointer
to void pointer and use %p specifier.
printf("Value of pi: %p\n", (void*)ptr);
NULL : interesting but misunderstood
The null pointer concept
The null pointer constant
The NULL macro
The ASCII NUL
A null String
The null statement

Similar but distinct concepts.


NULL : interesting but misunderstood
A null pointer and uninitialized pointers are different.
We can assign zero to any pointer
but not any other integer value.
May result in warning/error at
compile time and most probably in
segmentation fault* at run time.

int *ptr = 0 ; // fine


int *ptr = NULL; //fine
inr *ptr = 10; //NOT fine

A c-programmers worst nightmare.


Good practices
NULL should only be used in context of pointers.
whether use zero or NULL is a matter of personal
choice but using NULL reminds us that we are working
with pointers.
zero (0) changes value depending on context.

int *ptr = 0; // null pointer int *ptr;


*ptr = 0; // integer zero
null is good, but what is a void pointer now?

Pointer to void or void pointer - general purpose pointer


which can hold the address/reference of any data type.
int num=100; Point to remember :
int *ptr = #
printf("%p \n",ptr); sizeof() operator
Expressions can sizeof()
inside be usedoperator
with voidare
* but
not
notwith void.
evaluated.
void *pv = ptr; sizeof(void *);will
sizeof(k++) //okcompile and run fine but
ptr = (int *)pv; sizeof(void); // not
value of k will ok unchanged.
remain
printf("%p \n",ptr);
tips
Global and static pointers are by-default initialized to
NULL.
Size of pointer, irrespective of its type is 8 bytes (64
bit machine).
size_t type.
Dynamic memory
Allocation
Dynamic Memory Allocation
Problem -
Fixed size Arrays.
Prior knowledge of size is required.

Solution -
Allocate memory dynamically.

Dynamic memory management makes pointers so powerful/useful.


Dynamic Memory Allocation
Allocate memory
int *ptr = (int *) malloc (sizeof(int))

Use memory Free memory


*ptr = 5; free(ptr);
printf("*ptr: %d\n", *ptr);
Dynamic Memory Allocation functions
- malloc
- calloc Stdlib.h file
- realloc
- free

to case or not to cast ?


Malloc Vs Calloc
int *ptr = calloc(5, sizeof(int)); use calloc when
memory needs to be
is equivalent to zeroed out.
int *ptr = malloc(5*sizeof(int));
Calloc execution
memset(ptr , 0, 5*sizeof(int));
may take longer than
mallocs.
memset function fill the blocks of memory with value
specified.
Dangling Pointers
Even after memory is freed, pointer variable continue to
point to that location.
int *ptr = malloc(sizeof(int));
*ptr=5;
free(ptr);

Freed memory might have been overridden by some


other variable which even might not be an integer.
*ptr = 10; //undefined behaviour, dangling pointer
Handling - Dangling Pointers
- NULL assignment.
- Double free.
Both techniques will terminate the application if a
dangling pointer is used after it.
Memory Leak
When memory is allocated but is never used again or is
never freed.
- Either address is lost.
- or free is never invoked.

int *ptr = (int*) malloc(sizeof(int)); // this address will be lost


ptr = (int*) malloc(sizeof(int)); // because of this assignment.

Alway free the memory when task is done.


Functions and Pointer
Functions and Pointers
Two areas -
- Passing a pointer to function
- declaring a pointer to function

Heap , Stack and Stack Frame


(Activation record or activation
frame)
Passing a pointer to function
Very basic example - swapping two variables.
void swap( int* p1, int* p2)
{
int tmp;
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}

int main()
{
int n1 = 5;
int n2 = 10;
swap(&n1, &n2);
return 0;
}
Returning pointer from Function
- Declare the return type as pointer.
- Allocate memory inside function.
- return the pointer to allocated block of memory.
- function caller is responsible of deallocating the memory.
int* allocateArray(int size, int value)
{ int* vector = allocateArray(5,45);
int* arr = (int*)malloc(size *sizeof(int)); for(int i=0; i<5; i++)
for(int i=0; i<size; i++) {
{ printf("%d\n", vector[i]);
arr[i] = value; }
}
return arr;
}
Returning pointer from Function
To understand better, always heap
create a memory diagram.
Returning pointer from Function
Make sure you do not return address of local variable, i.e.
memory is allocated from heap only and not from stack.
Example -
int* allocateArray(int size, int value)
{ This arr is created in stack
int arr[size];
for(int i=0; i<size; i++)
frame of allocateArray
{ method and hence
arr[i] = value;
} address returned doesnt
return arr;
}
remain valid.
double pointer again.
void allocateArray(int **arr, int size, int value)
void allocateArray(int *arr, int size, int value)
{
{
int i;
int i;
*arr = (int*)malloc(size * sizeof(int));
arr = (int*)malloc(size * sizeof(int));
if(*arr != NULL)
if(arr != NULL)
{
{
for(i=0; i<size; i++)
for(i=0; i<size; i++)
{
{
*(*arr+i) = value;
*(arr+i) = value;
}
}
}
}
}
}
int main()
int main()
{
{
int *vector = NULL;
int *vector = NULL;
allocateArray(&vector,5,45);
allocateArray(&vector,5,45);
printf("%p\n",vector);
printf("%p\n",vector);
return 0;
return 0;
}
}
//Explain - Diagram of stack frames
Function Pointer - Introduction
void * fun (); void (* fun) ();

Just a function returning Function pointer.


void pointer and accepting Parentheses makes a
void. difference.

returnType functionPointerVariableName (parameter)


Function Pointer - Example
int (*fptr1)(int); int n = 5;
fptr1 = square;
printf("%d squared is %d\n",n, fptr1(n));
int square(int num)
{
return num*num;
}
Pointers and Arrays
Pointers and Arrays
- Arrays : Continuous collection of homogeneous elements that can
be accessed using an index.
- 2D Arrays : Array of Arrays, Row-major | Column-major
- Pointers and Arrays : Closely related, can be used interchangeably
in right context. Not completely interchangeable

- When arrays name is used, arrays address is returned.


- This address can be assigned to some pointer.
int arr[3] = {1,2,3}; int *pv = arr;
Pointers and Arrays
int arr[3] = {1,2,3};
arr return address of array / address of first element of array.
&arr is also used to obtain arrays address.
Difference? :
arr is the pointer to integer, the first element of array while &arr is
a pointer to complete array.
Pointer Arithmetic ?
Pointers and Arrays : Difference
int arr[3] = {1,2,3};
Elements can be accessed as arr[i](array notation) or arr+i(pointer
notation).
arr[i] equals *(arr+i).
Machine code difference :
arr[i] : starts at location arr, moves i positions, use content.
arr+i : starts at location arr, add i to the address, use content.
Pointers and Arrays : Difference
int arr[3] = {1,2,3};
int *ptr = arr; //ptr is pointer to array or say first element of array

sizeof(ptr); // 8 : pointers size


sizeof(arr); // 12 : bytes allocated to array.
ptr is lvalue - can be modified. ptr = ptr+1; //ok
arr - cannot be modified. arr = arr+1; //not ok
Pointers and Arrays : Similarity
Creating 1D array using malloc.

int *ptr = (int *)malloc(sizeof(int)*count));

for(i=0;i<count;i++){
*(ptr+i) = i;
}
Pointers and Arrays : 3 ways to think

1. Pointers can simulate arrays. Dynamic memory allocation.


2. Pointer arithmetic and array indexing are same.
3. pointers and array are different. One place they are same is formal
argument in function. Arrays are decayed in pointers. That is why
we can initialize array but cannot assign things to them except
when they are function parameters.

Example ?
Passing 1D-array to function
int arr[3] = {1,2,3}; Receiving and using 1D array:
func(arr); void func(int a[ ]) { a[i]; }

void func(int a[ ]) { *(a+i); }

void func(int *a) { a[i]; }

void func(int *a) { *(a+i); }

a will contain the address of arr.


Passing 2D array to function
int matrix[2][3] = {{1,2,3},{4,5,6}}; // 2D array

Declaring a pointer to 2D array -


int (*ptr)[3] = matrix;

(*ptr) is the pointer to array. complete declaration says ptr is a pointer


to 2D array of integers with 3 elements in each row.
Size of first dimension is known from matrix.
Passing 2D array to function
3 ways to pass 2D array to function
- void func( int a[][3], int rows){ //can use array subscripts}
- void func( int (*a)[3], int rows){ }
- void func( int *a, int rows, int columns) {
//cannot use array subscripts; for(int i=0; i<rows; i++) {
a[i][j]; //invalid for(int j=0; j<cols; j++) {
printf("%d ", *(arr + (i*cols) + j));
} }
printf("\n");
}
Array of Pointers

int* arr[5]; Memory Model ?


for(int i=0; i<5; i++) {
arr[i] = (int*)malloc(sizeof(int));
*arr[i] = i;
}

arr is the array of pointers. So arr[i] contains an address. *arr[i]


return the content of that address.
Array of Pointers

arr[i] = (int*)malloc(sizeof(int));
*arr[i] = i;

is equivalent to

*(arr+i) = (int*)malloc(sizeof(int));
*(*(arr+i)) = i;
Dynamically Allocating Arrays
1D:
int *vector = (int *) malloc(sizeof(int)*count);

2D:
int **matrix = (int **)malloc(rows * sizeof(int*));
for(i=0;i<rows;i++){
seperate malloc calls;
matrix[i] = (int *) malloc (columns* sizeof(int)); discontinous allocation
of memory
}
Dynamically Allocating Arrays
Continous allocation:

int *matrix = (int *)malloc(rows * columns * sizeof(int));

Вам также может понравиться