C Pointers
A C pointers is a variable that holds the memory address of another variable. Pointer variables are declared using the * operator, and they can point to various data types, including integers, characters, arrays, structures, and even other pointers. Manipulating pointers requires careful handling to avoid issues like memory leaks, dangling pointers, and segmentation faults.
int a;// An integerint *a;//A pointer to an integerint **a;//A pointer to a pointer to an integerint a[10];//An array of 10 integersint *a[10];//An array of 10 pointers to integersint (a)[10];//A pointer to an array of 1 integersint (a)(int);//A pointer to a function a that take an integer argument and return an integerint (*a[10]){int);//An array of 10 pointers to functions that take an integer argument and return an integer
Pointer
A pointer is a variable capable of holding the address of another variable. Dereferencing, accomplished with the (*) operator, allows accessing the value of the variable.
- Syntax :
Datatype * variable name ; - Syntax example :
int *p; - Rule : That two variables should be same data type.
Example
Int x=10; Int *p=&x; (Or) Int *p; p=&x;
- To access the value of x :
printf(“%d ”,p);—> value of x is 10 Orprintf(“%d”,(&x))—->value of x is 10 - To access addres of x:
printf(“%d”,p);—–> address of x is printed Orprintf(“%d”,&x);——> address of x
- Access the address of the variable syntax :
&variable_name - Declaring pointers syntax:
datatype *var;Example :int *a; - Initializing pointer syntax :
pointer_name =&variable_name;Example :int *a; int x; a =&x; - Pointer expressions :
- For addition
+, - For subtraction
-, - For increment
++, - For decrement
--.
- For addition
Declaration vs. Dereferencing
Although the spacing in a declaration like int *p; doesn’t matter, it’s important to understand the difference between declaring a pointer and using the dereference operator.
- Declaration: When you declare a pointer, the asterisk signifies that the variable will store a memory address.
- For example:C++
int* p; // 'p' is a pointer to an integer int* q, r; // 'q' is a pointer, but 'r' is a regular integerThis is a common pitfall. To declare multiple pointers on one line, you must put an asterisk before each variable:int *q, *r;.
- For example:C++
- Dereferencing: When you use the asterisk in an expression after a pointer has been declared, it’s the dereference operator. It means “go to the memory address stored in this pointer and get the value there.”
- For example:C++
int x = 10; int* p = &x; // 'p' stores the address of 'x' int value = *p; // 'value' becomes 10, the value at the address 'p' holdsHere, the asterisk has a completely different meaning from its use in the declaration.
- For example:C++
Advantage
- Use pointer to increase the speed of program execution
- Reduce program complexity
- To use pointer to access the inside function’s variable value.
- To use pointer to transfer the data from outside or inside the functions.
Void pointer
Void pointer is a pointer which can point to any datatype of memory block
But to access the complete memory one has to do type casting
- Syntax:
void *p;
Example:
int x=10; Char t =’u’; void *p; p=&x; printf(“ %d”,(int)p); // casting is done p=&t; printf(“ %c”,(char)p); // casting is done
What is the advantage of declaring void pointers?
Answer
When we do not know what type of the memory address the pointer variable is going to hold, then we declare a void pointer for such.
Function Pointer
A function pointer stores the address of a function, allowing it to be called later. This is useful as functions encapsulate behavior.
- syntax :
int(*fun)(int, int, int);
Example
#include <stdio.h>
// Function definitions
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return (b != 0) ? a / b : 0; }
// Typedef for function pointer
typedef int (*operation)(int, int);
int main() {
int x = 20, y = 5;
operation op;
// Addition
op = add;
printf("Add: %d\n", op(x, y));
// Subtraction
op = subtract;
printf("Subtract: %d\n", op(x, y));
// Multiplication
op = multiply;
printf("Multiply: %d\n", op(x, y));
// Division
op = divide;
printf("Divide: %d\n", op(x, y));
return 0;
}
NULL Pointers in C
A pointer pointing to nothing is called so.
- The NULL pointer always initializes.
- This pointer is a pointer that is not pointing to any valid memory in the heap.
- Null pointer holds the value a NULL value as its content.
Syntax :
Int *p=NULL;(address is 0 or null here);Int *p=0;is also called as null. but for our reference, we are using the NULL term
NULL pointer assignment:
*q=0; (or) <p>char *q=(char*)0; (or) char *p=NULL;
What is (void*)0 ? //Representation of NULL pointer
Answer
NULL Macro is defined in locale.h , stddef.h , stdio.h , stdlib.h , string.h , time.h , and wchar.h
Dangling Pointer
A pointer begins with a valid address but becomes a dangling pointer once that address is released or freed.
Near pointer
- Near pointer occupies 2 bytes in DOS, Windows and Linux
Far Pointer
- far pointer occupies 4 bytes in DOS, Windows and Linux
Huge Pointer
- huge pointer occupies 4 bytes in DOS, Windows and Linux
Other Pointers
| Type | Explanation | Example |
|---|---|---|
| Pointer to a Function | A pointer that holds the reference of a function is called a pointer to a function. | |
| Pointer to Pointer | one pointer refers to the address of another pointer | |
| pointer on pointer | It’s a pointer variable which can hold the address of another pointer variable. It de-refers twice to point to the data held by the designated pointer variable. | int x = 5,*p=&x, **q=&p; Therefore x can be accessed by *q |
Pointer and Array
int (ptr)[10];// ptr is a pointer to an array of 10 integers.
Example-1: POINTER TO AN ONE DIMENSIONAL ARRAY
#include<stdio.h>
int main ()
{
int a[3]={1,2,3};
int *p=(int*)&a;
// or
// int *p=a;
/*here a and &a RETURNS is same starting address only*/
printf("%d %d \n",p[0],p[1]);
printf("%d %d %d",*p,*(p+1),&a);
// here p[0] or *p is same only;
// p[1] or *(p+1) is same only
return 0;
}
Example-2: POINTER TO AN ONE DIMENSIONAL ARRAY
.#include<stdio.h>
int main ()
{
int a[3]={1,2,3};
int(*p)[3];
p=a;
printf("% d%d",(*p)[0],p[0][0]);
return 0;
}
Example-3: POINTER TO AN TWO DIMENSIONAL ARRAY
#include<stdio.h>
int main()
{
int a[2][2] = {{1,2},{3,4}}; //
int (*p)[2][2] = &a;
printf("%d\t",*p[0][0]);// it will print 1
printf("%d\t",p[0][0][0]); //HERE it means p[0][0]+0 it will print 1
printf("%d\t",(*p)[0][1]); //HERE it means p[0][0]+1 it will print 2
printf("%d\t",p[0][1][0]); //HERE it means p[0][1]+0 it will print 3
printf("%d\n",p[0][1][1]); // here it means p[0][1]+1 it will print 4
}
Example-4: POINTER TO AN TWO DIMENSIONAL ARRAY
#include<stdio.h>
int main()
{
int arr[2][2]={{1,2},{3,4}};
int (*p)[2]=arr;
printf("%d%d%d%d",*(*p),*(*p+1),**(p+1),*(*(p+1)+1));
return 0;
}
Example-5: POINTER TO STRINGS
STRING is an one dimensional array of char data type
#include<stdio.h>
int main ()
{
char p[]="muthu"; /* here p[] and *p are same */
printf("%s\n",p); /*it prints muthu */
printf("%d\n",p); /* here p holds starting address 0th location*/
printf("%d\n",p+1);/* here p+1 holds address of 1st location */
printf("%d\n",p+2);/* here p+2 holds address of 2nd lcn*/
printf("%d\n",p+3);/* here p+3 holds address of 3rd lcn*/
printf("%d\n",p+4);/* here p+4 holds address of 4th lcn*/
printf("%c",*p); /* *p holds value at 1st addres*/
printf("%c",*(p+1));/* *(p+1) holds value at 1st addres*/
printf("%c",*(p+2));/* *(p+2) holds value at 1st addres*/
printf("%c",*(p+3));/* *(p+3) holds value at 1st addres*/
printf("%c\n",*(p+4));/* *(p+4) holds value at 1st addres*/
return 0;
}
Example-6: POINTER TO STRINGS
#include<stdio.h>
int main ()
{
char p[]="muthu";
printf("%d\n",p); /* prints starting addres*/
char *t=p; /* valid initialization */
/* char t[]=p; error invalid initialization WE CAN ONLY USE *t to
initial string value from another variable but not using t[] only * operator is used for
dereferencing */
/* u can also initialize the new pointer variable using the existing variable */
printf("%d\n",t); /* prints starting addres*/
char *s=t;
printf("%d\n",p); /* prints starting addres*/
printf("%s",s);
return 0;
}
Example-7: WHAT HAPPENS IF YOU PRINT FUNCTION NAME WHAT VALUE IT PRINTS
#include<stdio.h>
void muhtu()
{
}
main()
{
printf(“%d”,muhtu); // it prints the address of the function
}
Call by reference in C Pointers
Call by reference allows passing the address of a variable as an argument, enabling modifications to the variable within the called function. This means changes to the formal parameter value can affect the actual arguments.
Example swapping of two numbers
#include<stdio.h>
void main( )
{
int a = 10, b = 20 ;
printf ( "value before swap\na = %d b = %d\n", a, b ) ;
swapr ( &a, &b ) ;// calling function
printf ( "value after swap\na = %d b = %d", a, b ) ;
}
swapr( int *x, int *y )
{
int t ;
t = *x ;
*x = *y ;
*y = t ;
}
- The calling function invokes or calls the function, while the called function executes due to the call.
Example of PASSING ARRAY TO FUNCTION USING CALL BY VALUE
#include<stdio.h>
#include<stdlib.h>
struct Array
{
int arr[5];
};
void passbyvalue(struct Array temp)
{
temp.arr;
int i;
for (i = 0; i <5; ++i)
printf("%d ", temp.arr[i]);
printf("\n");
}
int main()
{
int i;
struct Array obj=
{
{1,2,3,4,5}
};
for (i=0; i<5; i++)
obj.arr[i];
for (i = 0; i <5; ++i)
printf("%d ", obj.arr[i]);
passbyvalue(obj);
return 0;
}
int *const ptr; & int const *ptr;
constto the left of*→ data cannot change.constto the right of*→ pointer address cannot change.
Pointer Declaration Rules Recap
| Declaration | Meaning |
|---|---|
int *const ptr; | Constant pointer to an integer. (Address cannot change; value can change) |
int const *ptr; | Pointer to a constant integer. (Value cannot change; address can change) |
Practice Examples
| Declaration | Meaning |
|---|---|
int const *ptr = &arun; | Pointer to a constant int (cannot change value at address, can change the address) |
int *const ptr = &arun; | Constant pointer to int (cannot change address, can change value) |
const int *const p = &q; | Constant pointer to a constant int (cannot change address or value) |
Understanding const placement
Rule of thumb:
Read the declaration right-to-left.
Example:
int * const ptr→ptr is a const pointer to intconst int * ptr→ptr is a pointer to a const int
Common shorthand:
| Declaration | Meaning |
|---|---|
int const *ptr | Pointer to const int |
int * const ptr | Const pointer to int |
int const * const ptr | Const pointer to const int |
Decoding complex cases
| Declaration | Meaning |
|---|---|
int ** const | Const pointer to pointer to int |
int * const * | Pointer to const pointer to int |
int const ** | Pointer to pointer to const int |
int * const * const | Const pointer to const pointer to int |
Reference Video
Interview Questions
Difference between int* p and int *p??
Answer
int* p and int *p are exactly the same in C and C++. The spacing between the type (int), the asterisk (*), and the variable name (p) is ignored by the compiler. The asterisk is associated with the type to declare a pointer, or with the variable name to indicate it’s a pointer. Most programmers prefer int* p to emphasize that p is a pointer to an integer. The alternative, int *p, might be used to show that the asterisk applies to the variable p itself, not the type int.
Difference between const char *P and char Const *P
Answer
| Declaration Syntax | Name | Can reassign? | Can modify pointer? |
|---|---|---|---|
const Type* myPtr | Pointer-to-const | Yes | No |
Type const* myPtr | Pointer-to-const | Yes | No |
Type* const myPtr | const pointer | No | Yes |
const Type* const myPtr | const pointer-to-const | No | No |
Type const* const myPtr | const pointer-to-const | No | No |
Pointer hold the another Const pointer?
Answer
Yes can hold another conts pointer
Previous & Next
- Previous : C Array
- Next : C Functions