Swarnim Khosla
Swarnim Khosla

Reputation: 237

Segmentation Fault: Dynamically allocating matrix using a double pointer

Trying to understand the usage and memory allocation of double pointers in C.

Below is my code: -

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    
    printf("Enter rows and columns respectively: -\n");
    
    int rows, columns;
    scanf("%d%d", &rows, &columns);
    
    int **matrix;
    
    matrix = calloc(rows, sizeof(int));
    
    int i, j;
    for(i = 0; i < rows; i++)
    {
        matrix[i] = calloc(columns, sizeof(int));
    }
    
    printf("Enter your elements\n");
    
    for(i = 0; i < rows; i++)
    {
        for(j = 0; j < columns; j++)
        {
            scanf("%d", &matrix[i][j]);
        }
    }
    
    printf("Your elements are: -\n");
    
    for(i = 0; i < rows; i++)
    {
        for(j = 0; j < columns; j++)
        {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    
    free(matrix);
    
    return 0;
}

After getting Segmentation fault: 11, I searched on the net and found out that instead of writing this: -

int **matrix;
matrix = calloc(rows, sizeof(int));

I should write: -

int **matrix;
matrix = calloc(rows, sizeof(int*));

After making the above changes, my code works fine.

My question is: -

  1. What is the difference between sizeof(int) and sizeof(int *)?
  2. Don't both of them allocate 4 bytes? (int occupies 4 bytes and int* (which is noting but a pointer) also occupies 4 bytes?
  3. If both of them allocates the same space, then why was I getting a Segmentation fault in the first case?

Upvotes: 0

Views: 238

Answers (1)

Konrad Rudolph
Konrad Rudolph

Reputation: 545588

Don't both of them allocate 4 bytes? (int occupies 4 bytes and int* (which is noting but a pointer) also occupies 4 bytes?

What makes you think that a pointer is four bytes? On most modern (64 bit) architectures, pointers to object are 8 bytes, not 4.

Hence, in general sizeof(int) ≠ sizeof(int *). But you can’t make many assumptions about the sizes of objects in portable C code, and you definitely can’t assume that sizeof(int) == 4, or sizeof(int*) == 8 (nor 4). Depending on the platform, these sizes vary. They could also have the same size. You just can’t assume that.

To avoid confusion between pointer and pointee size, some people (me included) recommend using the object name in the sizeof expression in allocations, rather than the type name:

int **matrix = calloc(rows, sizeof *matrix);
// …
matrix[i] = calloc(columns, sizeof **matrix);

This makes it clear what you are trying to allocate. Note that sizeof expr does not evaluate expr; this is important, since the expressions *matrix and **matrix are invalid before you’ve allocated the memory — deferencing the unassigned pointer would be undefined behaviour. But sizeof only determines the object size of the expression without actually evaluating it.

Upvotes: 2

Related Questions