-
int (*ptr)[10] is a pointer to an array of 10 integers.
e.g.
int arr[10]={1,2,3}; int (*ptr)[10]; ptr = &arr;//ptr points to array arr
- int *ptr is a pointer to an integer
e.g.int a = 12; int *b; b = &a;
- int (*ptr)(int) is a pointer to a function which takes one integer parameter and returns an integer
e.g.int cube(int n); int (*ptr2)(int); ptr2 = cube;
Both malloc and calloc allocate memory dynamically and return a pointer to begining of block allocated.
But the difference is malloc allocates memory block, but does not initialize the values inside the block.
Calloc allocates memory and initializes each bit with 0 after allocating.
Calloc takes two parameters - number of elements to be allocated and size of one element and malloc takes only one parameter - total size to be allocated.
Both of these functions return a pointer to allocates block.
int *ptr1,*ptr2; ptr1 = (int*)malloc(20*sizeof(int)); ptr2 = (int*)calloc(20,sizeof(int));/*the block has all 0 values*/
realloc is used to change the size of memory block allocated. If there is insufficient place, it moves the block to a different address.
It takes two parameters - pointer and its new size.
realloc(ptr1,40*sizeof(int));
Here the memory block is expanded to hold 40 integers and ptr1 points to begining of block.
Note that
- if ptr1 in the above example is NULL, realloc works exactly like malloc.
- If second parameter (new size) is 0, realloc works like free
You should type cast the pointer to the required type with all these functions.
Yes, no and yes.
- void function : If a function does not return anything, its return type should be void. Such a function still can contain empty return statement.
e.g.void print_larger(int a,int b) { if(a>b) { printf("%d",a); return; } printf("%d",b); }
- void variable : We can not have a void variable.
- void pointer: We can have a void pointer which is a generic pointer. Void pointer can be type-cast and used to point at any type of variable. The dynamic memory allocation functions malloc, calloc and realloc do return a void pointer.
void *ptr; int a =12; ptr = (int*)&a;//ok a = *ptr+10;/*error. typecasting should be used*/
[P1] int * g (void) { int x = 10; return (&x); } [P2] int * g (void) { int * px; *px = 10; return px; } [P3] int *g (void) { int *px; px = (int *) malloc (sizeof(int)); *px = 10; return px; }Which of the above three functions are likely to cause problems with pointers?
Both P1 and P2
P1 may not behave correctly because the function returns address of a local automatic variable which will not exist once the function terminates.
P2 causes run time error because px is derefernced without initializing it.
#include<stdio.h> void f(int *p, int *q) { p = q; *p = 2; } int i=0, j=1; int main() { f(&i, &j); printf("%d %d \n", i, j); return 0; }
Output : 0 2
char c[] = "A tricky question"; char *p =c; printf("%s", p + p[2] -p[3]) ;
Output : tricky question
p is character pointer and it points to the string A tricky question. When you add p[2]-p[3] to p, it becomes p+'t'-'r' = p+2. Which points to the string tricky question
void func(int ( *p)[3]); int main(){ int x[2][3] = { {4,5,6},{7,8,9}}; func(x); func(x+1); } void func(int (*p)[3]) { printf("%d %d %d\n",(*p)[0],(*p)[1],(*p)[2]); }
Output:
4 5 6
7 8 9
The parameter p to the function func() is a pointer to one dimensional array. When the function is called with x, the argument will be x[0] - the 0th of the array. When next it is called with x+1, the argument sent will be 1st row of the matrix. The function dereferences the pointer and prints the 0th , 1st and 2nd element of this sub-array.
const char *p1; char * const p2;
p1 is a pointer to a character constant. Which means character pointed by p1 is constant. But the pointer is not constant.
*p1 = 'z' ;would be wrong.
p1 = "aaa" ;- is fine.
p2 is a constant pointer to a character. Here pointer is constant. But character is not. Which means we can not assign another value to p2. But we can change the character pointed by p2
p2 = "mnop" ;is wrong
*p2 = 'a' ;is fine
We can even have
const char * const p3 = "Hello world";
p3 is a constant pointer to constant character. Here neither address nor character can be modified.
Another point of interest is all pointers assigned to string literals are pointers to char constants. Which means the strings they are pointing to can not be modified.
char *str = "Hello world"; *str = 'h';Second line in the above code causes the program to crash in some systems. Modifying a string literal produces an undefined behavior.
int insertionsort(int *arr,int n) { int i,j,temp; for(i=1;i<n;i++) { temp=*(arr+i); j=i-1; while(temp<*(arr+j)&&j>=0) { *(arr+(j+1))=*(arr+j); j--; } *(arr+(j+1))=temp; } return 0; }
#include <stdio.h> #include <string.h> int main() { char *str = "hello, world\n"; char *strc = "good morning\n"; strcpy(strc, str); printf("%s\n", strc); return 0; }
The program crashes with segmentation fault
The program tries to modify a value pointed by strc which is a pointer pointing to a string literal. Such a pointer is a pointer to a constant character - the value pointed by such a pointer can't be modified. Hence the program crashes.
#include <stdio.h> int main() { char *str = "hello, world\n"; str[5] = '.'; printf("%s\n", str); return 0; }
Crashes with segmentation fault
str is a pointer to a string literal. Such a string literal will be normally stored in a read only section. That is why we can't change the charactes of this string.
#include <stdio.h> int main() { char *str = "hello world"; char strary[] = "hello world"; printf("%d %d\n", sizeof(str), sizeof(strary)); return 0; }
4 and 12 in 32 bit machines.
str is a pointer. So its size is the same as size of a pointer - which is size of an integer.
strary is a string array with 11 characters. But its size is 12 - because of the trailing null character - '\0'. (Strings always have null character as last character.)
A dangling pointer is the one which is used after the memory allocated to it is released using free. Because the pointer is not pointing to any valid address, the result is unpredictable.
int *ptr = malloc(100*sizeof(int)); ------- ------ free(ptr); *ptr = 12;/*using ptr after free. dangling pointer*/
NULL pointer is a predefined pointer pointing to location 0. It is defined as (void*)0 in stdio.h and stdlib.h. Functions which return a pointer, often return NULL to indicate failure.
Null pointer should never be derefernced. If it is derefernced, the program will crash.
If memory blocks allocated dynamically in a program (using malloc or calloc) are not released using free(), your program will run out of heap memory in due time. This is called memory leak.
A void pointer is a generic pointer. It is defined as
void *ptr;This void pointer can be used to store address of any type of variable.
But if a void pointer is deferenced without type casting, compiler gives error.
void *ptr; int a; float b; ptr = (int *)&a; ptr = (float*)&b; *ptr=5;/*syntax error*/ *(int *)ptr = 5;//correct
malloc, calloc and realloc return a void pointer.
Only operations allowed with pointers are :
- You can add or subtract an integer to a pointer.
- You can subtract 2 pointers.
e.g. if you add 1 to integer pointer in 32 bit machine, the pointer gets incremented by 4 bytes so that it can point to next integer.
int a;float b;double c; char d; int *ptr1 = &a;/* say a is at location 1000 and it is 4 byte machine*/ float *ptr2 = &b;/*say b is at location 3000*/ double *ptr3 = &c;/*say c is at location 4000*/ char *ptr4 = &d; ptr1++;/*now ptr1 is 1004*/ ptr1 +=5;/*now ptr1 is 1024*/ ptr2 = ptr2 - 3;/*now ptr2 is 2988 */ ptr3++;/* now ptr3 is 4008*/ ptr4+=5;/*ptr4 is 4005*/ ptr1*=2;/* error*/ ptr2 = ptr1+ptr2;/*error*/
int *(*x)(char*)
It is not converted to a pointer when using & (address of ) operator and when using sizeof operator.
int arr[3]={1,2,3}; arr[1]=24;/* is converted to *(arr+1) = 24*/ add_num(arr,12);/* parameters sent are &arr[0] and 12*/ l = sizeof(arr);/* is 3*sizeof(int) . Not sizeof(&arr[0]) */ int *ptr = &arr+1;/* if arr is stored at 1000, ptr will be 1012. no implicit conversion*/
#include<stdio.h> int main() { int a,b,c,d; char *p = ( char *)0; int *q = ( int *)0; float *r = ( float *)0; double *s = 0; a = (int)(p+1); b = (int)(q+1); c = (int)(r+1); d = (int)(s+1); printf("%d %d %d %d",a,b,c,d); return 0; }
1 4 4 8
for 32 bit computer
When you perform any arithmetic operations on pointers, these are scaled by the size of the pointee. If you add 1 to an integer pointers, you infact will add 4 to the number.
If you add 1 to double pointer, it gets added by 8 and so on.
#include<stdio.h> int main() { int i = 3; int *j; int **k; j = &i; k = &j; printf("%u %u %u",i,*j,**k); return 0; }
3 3 3
Here j is a pointer to integer and it points to i. Which means *j is i.
k is a pointer to pointer to integer and it points to j. And **k is again i. So the program prints the value of i three times.
# include <stdio.h> void fun(int x) { x = 30; } int main() { int y = 20; fun(y); printf("%d", y); return 0; }
x is a value parameter to the function fun(). So x is another copy of y. Which means changing x will not change y. Hence the program will print 20 instead of 30.
To fix the problem, you need to send a reference paramter as shown below
void fun(int *x) { *x = 30; } int main() { int y = 20; fun(&y);/*send address of y to function*/ printf("%d",y); return 0; }
Other method is by returning a value from function fun
int fun(int x) { x = 30; return x; } int main() { int y = 20; y = fun(y); }
#include <stdio.h> int main() { float arr[5] = {12.5, 10.0, 13.5, 90.5, 0.5}; float *ptr1 = &arr[0]; float *ptr2 = ptr1 + 3; printf("%f ", *ptr2); printf("%d", ptr2 – ptr1); return 0; }
90.5 3
ptr1 points to 0th element of the array. When we add 3 to ptr, the result will be pointer to 3rd element of the array. Hence the program prints arr[3].
#include<stdio.h> int main() { int a; char *x; x = (char *) &a; a = 512; x[0] = 1; x[1] = 2; printf("%d\n",a); return 0; }What is the output of above program?
513
x is a character pointer. So x[0] will p
int arr[3] = {1,22,333}; 2[arr]= 44;
Though the statement looks ridiculous, it is correct.
C compiler converts any array expression into a pointer expression.
So arr[3] = 3[arr] =*(arr+3)
int* a1[8]; int (*a2)[8]; int (*a3)(int[]);
- a1 is an array of 8 integer pointers.
- a2 is a pointer to an array of 8 integers.
- a3 is a pointer to a function which takes integer array as a parameter and returns an integer
#include <stdio.h> int main() { char *a = {"p", "r", "o", "g", "r", "a", "m"}; printf("%s", a); }
What is the output of this program?
p
If you expect the output to be program, you are wrong. Elements of array are enclosed in double quotes. So they are character strings, not characters. That's why a will be pointing to first string p.
To make a point to the string program , you can define it as
char *a = {'p','r','o','g','r','a','m','\0'};
#include<stdio.h> int main() { int arr[] = {12, 13, 14, 15, 16}; printf("%d, %d, %d\n", sizeof(arr), sizeof(*arr), sizeof(arr[0])); return 0; }
20 4 4
Size of arr = number of elements X size of each element in bytes = 5X4 = 20.
*arr and arr[0] both are 0th element of the array and their size is 4 bytes each.
#include<stdio.h> int sum(int a,int b,int c) { return a+b+c; } int product(int a,int b,int c) { return a*b*c; } int operate(int(*fptr)(int,int,int),int a,int b,int c) { return fptr(a,b,c); } int main() { int x,y,z; x = 2;y=4;z=6; printf("product is %d\n",operate(product,x,y,z)); printf("sum is %d\n",operate(sum,x,y,z)); }
void swap(int *ptr1,int *ptr2) { *ptr1 = *ptr1+*ptr2; *ptr2 = *ptr1-*ptr2; *ptr1 = *ptr1-*ptr2; } int main() { int i=10,j=20; swap(&i,&j); return 0; }
#include<stdio.h> typedef int * INTPTR; int main() { INTPTR p1,p2; int a,b; a = 10; b = a; p1 = &a; p2 = &b; printf("Sum of a and b is %d\n", *p1+*p2 ); return 0; }
A pointer is defined with its name, type of pointee and the symbol *.
Syntax
data-type * var-name;
e.g.
int *ptr; float *p2;
Here we are defining ptr as integer pointer and p2 as float pointer.
To assign an address to it, we use & (address of) operator.
int a = 10; int *ptr; ptr = &a;
Now ptr points to a.
An indirection operator is used to give value at the address specified by ptr. This operator is the same used for multiplication also - *
int *ptr; int a; ptr = &a; *ptr = 12;
Now *ptr gives us "a".
The statement *ptr=12 assigns 12 to a indirectly.
Indirection operator and address of operator (* and &) are complimentory to each other.
A function pointer is a pointer which stores address of a function.
If void foo();
is a function, then foo (without paranthesis) or &foo is address of this function and is also a function pointer.
To define a function pointer syntax used is
ret-type (*name)(parameter-list);
e.g.
void (*ptr)()is a function pointer which points to a function which takes no parameter and returns nothing.
Similarly to define a function pointer which takes an array and int as parameter and returns int, we should write
int (*ptr)(int arr[],int n)
Function pointers are used to implement call back functions
A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.
A function pointer is a pointer which holds address of a function.
e.g.int (*ptr)(int,int)
This defines ptr as a function pointer to a function which returns an integer and takes two integer parameter.
Remember that type of a pointer to a function is based on both the return type and parameter types of the function. Also, declaration of a pointer to a function must have the pointer name in parentheses.
Next this pointer must be assigned to address of a function with similar signature.Let us say sum function.
ptr = sum;or
ptr = &sum ;
sum should be of the type
int sum(int a,int b);
To invoke sum() using function pointer, we must dereference it and provide arguments if needed.e.g.
int ans = (*ptr)(10,10);
This calls sum function with parameters 10 and 10.
- Pointer to an integer
- Pointer to pointer to integer
- Pointer to an array of 3 integers
- Array of 3 integer pointers
- Pointer to function which return an int and takes an int parameter.
- int *ptr;
- int **ptr;
- int (*ptr)[3];
- int *ptr[3];
- int (*ptr)(int);