Pointer is one of the most confusing concept in c and c++, In this blog post we are going to make it easy to understand this concept.
#Types and memory
When we declare a vaialbe or store any data temporarily the computer will reserve memory for this variable or data and it will store that variable or data in the reserved space in byte.
The example of the memory structure representation we are going to use to understand pointers is
Where the address is just put in numbers to make it easy to understand, normally it is put in hexadecimal, variable is the name and the value is the assigned ascii number attached to the variable.
Depending on the type of a variable the computer will reserve a vary amount of space in memory.
1 byte = 8 bits, each bit being 0 or 1
char = 256 different value = 2^8 = 8 bits = 1 byte
int = 4294967296 different
value = 2^32 = 32 bits = 4 byte
float = 4294967296 different value = 2^32 = 32 bits = 4 byte
You can check the size of a variable type using sizeof
operator.
Example
When we declare a variable l
of type char
.
char l;
Int this example we created the address of l is 6.
char l;
l = 'A';
We assigned the value 'A'
to the variable l
but the byte will not hold a letter 'A'
, it will hold ascii code, which is 65 (man ascii).
In the int
and float
case we use 4 bytes.
int n;
n = 8;
& operator
when we want to find the address of a variable we use the & operator.
Example
The modifier
%p
is used to print address
#Storing memory addresses
Up to now we learned how to store a character, decimal and floats in a variable.
We also learned how to get the address of variable using &
operator.
pointer is simply the address of a piece of data in memory.
pointer variable is a variable that stores the address of that piece of data.
To declare a pointer variable
VARIBALE_TYPE *VARIABLE_NAME
Example
char *p;
A pointer variable holds the address of other variable data
A pointer variable has a size of 8 byte
A pointer variable has his own variable address
Example
int n;
int *p;
n = 10;
p = &n;
Now the address of n is 3 and the address of n is &n, So we stored the address of n in p pointer variable.
In this example the the address of n is 3,then the value of p is 3 which holds the address of n.
#Dereferencing
Dereferencing is a way of using pointers manipulate values stored at the memory address they point to.
We use the * dereference operator to Dereference the value.
First off * has two functions
used in the declaration. e.g
int *p;
used in dereferencing. e.g
*p = 20;
Example
int n;
int *p;
n = 11;
p = &n;
*p = 20;
So now:
p == &n
holds the address of n*p == n
points the value of n
Now let's break this example using the memory representation.
Up to the part n = 11 and p = &n = 7 the memory representation is
After dereferencing *p = 20
the memory will look like this
#Functions parameters are passed by value
We have covered in the c function blog post that there are two way of passing parameter in functions.
Pass by value: passing the copy of the variable.
Pass by reference: passing the pointer to the variable.
Pass by value: this method only copies the value of the variable in the main function and the change made in the other function doesn't affect the value in the main function because it is just a copy.
Example
Before the execution of i = 20;
the memory layout looks like this
After the execution of the i = 20;
the memory layout will look like this
When the fun is done executing the variable i is removed and the memory layout looks like this
To modify a variable from outside the function it is declared, using a pointer.
Before the function fun the memory layout looks like this
when we call the function fun the value of p
is stored in a new variable called i
.
Since i stores the same memory address, it points to the same address, and so both p and i now point to n. Therefore, when we execute the line *i = 20; we modify the value of n and n now holds 20.
When we leave the function fun, the variable i is destroyed, but i’s value is still 20
#Arrays
Arrays in C are contiguous memory areas that hold a number of values of the same type and all elements of an array have the same type.
To declare an array
TYPE ARRAY_NAME[ARRAY_SIZE];
To assign a value
TYPE ARRAY_NAME[ARRAY_SIZE] = {ELEMENTS}
Example
int arr[5];
arr[0] will access the first element, arr[1] the second element, and so on.
In this example the computer will reserve a continuous space for 5 integers in memory.
The memory layout will look like
#Pointers vs Arrays
Arrays are not pointers they don't hold memory address, But the name of an array is the address of the first element of the array.
Example
So why this it outputting the address, when an array a
is used in an expression the array type gets automatically implicitly converted to pointer-to-element type(array type decay).
There are two exceptions to this rule in two cases:
-
sizeof()
operator
Example
-
&
operator
Example
#Pointers Arithmetic
We can access the elements of an array using a different method as *(var + x), where var is the name of an array, and x is the (x+1)th element.
Example
The memory is a layout
#Strings
Strings are actually one-dimensional array of characters terminated by a null character '\0'.
TYPE STRING_NAME[SIZE] = {ELEMENT}
Example
You probably notice that we used an array with a size of 6,this is because in C, strings end with the char '\0' (ascii value = 0).
#Memory Layout of C program
Memory layout of C program contains five segments:
stack segment
heap segment
BSS (block started by symbol)
DS (Data Segment)
text segment
Each segment has own read, write and executable permission. If a program tries to access the memory in a way that is not allowed then segmentation fault, which is a common problem that causes programs to crash.
stack
The stack contains local variables from functions, return value and each function has one stack frame.
The stack contains a LIFO(last in first out) structure, Function variables are pushed onto the stack when called and functions variables are popped off the stack when return.
To understand how LIFO work check out the stack data structure.
#include <stdio.h>
int main(void)
{
int data; //local variable stored in stack
return 0;
}
Heap
Heap is used to allocate the memory at run time and heap area managed by the memory management functions like malloc, calloc, free, etc
#include <stdio.h>
int main(void)
{
char *pStr = malloc(sizeof(char)*4); //stored in heap
return 0;
}
BSS(Uninitialized data segment)
It contains all uninitialized global and static variables.
#include <stdio.h>
int data1;
// Uninitialized global variable stored in BSS
int main(void)
{
static int data2;
// Uninitialized static variable stored in BSS
return 0;
}
DS(Initialized data segment)
It contains the explicitly initialized global and static variables and this segment can be further classified into an initialized read-only area and an initialized read-write area.
#include <stdio.h>
int data1 = 10 ;
//Initialized global variable stored in DS
int main(void)
{
static int data2 = 3;
//Initialized static variable stored in DS
return 0;
}
Text
The text segment contains a binary of the compiled program and he text segment is a read-only segment that prevents a program from being accidentally modified.
#include <stdio.h>
int main(void)
{
return 0;
}
Tip:
NULL
is for pointers which is the absence of address and '\0' is the is for strings
Top comments (0)