Home > database >  different ways to declare a matrix c
different ways to declare a matrix c

Time:11-23

I don't really understand why method 1 works but not method 2. I don't really see why it works for characters and not an int.

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
    ///  WORK (METHODE 1)
    char **string_array = malloc(sizeof(char **) * 10);
    string_array[0] = "Hi there";
    printf("%s\n", string_array[0]); /// -> Hi there
    
    /// DOES NOT WORK (METHODE 2)
    int **int_matrix = malloc(sizeof(int **) * 10);
    int_matrix[0][0] = 1;  // -> Segmentation fault
    
    /// WORK (METHODE 3)
    int **int_matrix2 = malloc(sizeof(int *));
    for (int i = 0; i < 10; i  )
    {
        int_matrix2[i] = malloc(sizeof(int));
    }
    int_matrix2[0][0] = 42;
    printf("%d\n", int_matrix2[0][0]); // -> 42
}

CodePudding user response:

In terms of the types, you want to allocate memory for the type "one level up" from the pointer you're assigning it to. For example, an int pointer (an int*), points to one or more ints. That means, when you allocate space for it, you should allocate based on the int type:

#define NUM_INTS 10
...
int* intPtr = malloc(NUM_INTS * sizeof(int));
//                                      ^^ // we want ints, so allocate for sizeof(int)

In one of your cases, you have a double int pointer (an int**). This must point to one or more int pointers (int*), so that's the type you need to allocate space for:

#define NUM_INT_PTRS 5
...
int** myDblIntPtr = malloc(NUM_INT_PTRS * sizeof(int*));
//                                               ^^ "one level up" from int** is int*

However, there's an even better way to do this. You can specify the size of your object it points to rather than a type:

int* intPtr = malloc(NUM_INTS * sizeof(*intPtr));

Here, intPtr is an int* type, and the object it points to is an int, and that's exactly what *intPtr gives us. This has the added benefit of less maintenance. Pretend some time down the line, int* intPtr changes to int** intPtr. For the old way of doing things, you'd have to change code in two places:

int** intPtr = malloc(NUM_INTS * sizeof(int*));
// ^^ here                              ^^ and here

However, with the 2nd way, you only need to change the declaration:

int** intPtr = malloc(NUM_INTS * sizeof(*intPtr));
// ^^ still changed here                 ^^ nothing to change here

With the change of declaration from int* to int*, *intPtr also changed "automatically", from int to int*. This means that the paradigm:

T* myPtr = malloc(NUM_ITEMS * sizeof(*myPtr));

is preferred, since *myPtr will always refer to the correct object we need to size for the correct amount of memory, no matter what type T is.

CodePudding user response:

The method 1 works only becuse you assign the char * element of the array string_array with the reference of the string literal `"Hi there". String literal is simply a char array.

Try: string_array[0][0] = 'a'; and it will fail as well as you will dereference not initialized pointer.

Same happens in method 2.

Method 3. You allocate the memory for one int value and store the reference to it in the [0] element of the array. As the pointer references the valid object you can derefence it (int_matrix2[0][0] = 42;)

  • Related