DEV Community šŸ‘©ā€šŸ’»šŸ‘Øā€šŸ’»

Cover image for C - Pointers, arrays and strings
Haile Melaku
Haile Melaku

Posted on • Updated on

C - Pointers, arrays and strings

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

Image description

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;
Enter fullscreen mode Exit fullscreen mode

Image description

Int this example we created the address of l is 6.

char l;

l = 'A';
Enter fullscreen mode Exit fullscreen mode

Image description

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).

Image description

In the int and float case we use 4 bytes.

int n;  

n = 8;
Enter fullscreen mode Exit fullscreen mode

Image description

& operator

when we want to find the address of a variable we use the & operator.

Example

Image description

Image description

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;
Enter fullscreen mode Exit fullscreen mode

Image description

Image description

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

Image description

Example

int n;
int *p; 

n = 10;
p = &n; 
Enter fullscreen mode Exit fullscreen mode

Image description

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.

Image description

Image description

Image description


#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; 
Enter fullscreen mode Exit fullscreen mode

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

Image description

Image description

After dereferencing *p = 20 the memory will look like this

Image description

Image description

Image description

Image description


#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

Image description

Before the execution of i = 20; the memory layout looks like this

Image description

Image description

After the execution of the i = 20; the memory layout will look like this

Image description

Image description

When the fun is done executing the variable i is removed and the memory layout looks like this

Image description

Image description

To modify a variable from outside the function it is declared, using a pointer.

Image description

Before the function fun the memory layout looks like this

Image description

Image description
when we call the function fun the value of p is stored in a new variable called i.

Image description

Image description

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.

Image description

Image description

When we leave the function fun, the variable i is destroyed, but iā€™s value is still 20

Image description

Image description


#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];
Enter fullscreen mode Exit fullscreen mode

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.

Image description

Image description

The memory layout will look like

Image description


#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

Image description

Image description

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

Image description

Image description

  • & operator

Example

Image description

Image description

#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

Image description

Image description

The memory is a layout

Image description


#Strings

Strings are actually one-dimensional array of characters terminated by a null character '\0'.

TYPE STRING_NAME[SIZE] = {ELEMENT}

Example

Image description

Image description

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).

Image description


#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.

Image description

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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; 
}
Enter fullscreen mode Exit fullscreen mode

Image description

Tip: NULL is for pointers which is the absence of address and '\0' is the is for strings

Top comments (0)

Make Your Github Profile Stand Out

Github is great, but have you considered how to make yours more attractive for potential employers or other visitors? Even non-tech ones like recruiters!

Take a couple of hours and show your best side as a person - and a programmer.