2

I'm trying to code a function that would ask the user to enter matrix. It prompts the number of lines, the number of columns and then prompts the value for each element of the matrix:

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

void enterMatrix(float ** matrix, int nbLines, int nbColumns){
    for (int i = 0; i < nbLines * nbColumns; i++){
        printf("i = %d? ", i);
        scanf("%f", matrix[i]);
    }
}

int main(void){
    int nbLines, nbColumns;
    printf("nbLines? "); scanf("%d", &nbLines);
    printf("nbColumns? "); scanf("%d", &nbColumns);
    float *matrix[nbL * nbCol];

    enterMatrix(matrix, nbLines, nbColumns);
}

Everything works fine until I enter a value for i = 0 and then press enter, which leads to a segmentation fault.

Any idea as to what could be wrong?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
AlexT
  • 589
  • 2
  • 9
  • 23

4 Answers4

3

Your problem is because

float *matrice[nbL * nbCol];

defines an array of uninitialised pointers (i.e. an array of float *), not an array of float. This is then passed to enterMatrix() as a pointer to pointer to float (i.e. a float **). The scanf() calls then read to matrix[i] which is an uninitialised pointer. The result is undefined behaviour.

One fix would be to change the definition of matrice in main() to

float matrice[nbL * nbCol];

and change the function to (I've used comment to highlight changes)

void enterMatrix(float *matrix, int nbLines, int nbColumns)    /*  note type of matrix  */
{
     for (int i = 0; i < nbLines * nbColumns; i++)
     {
         printf("i = %d? ", i);
         scanf("%f", &matrix[i]);      /*  note what the second argument is */
     }
}
Peter
  • 35,646
  • 4
  • 32
  • 74
2

You need to allocate memory dinamically since you do not know at compile time which values the variables nbLines and nbColumns will hold.

So you need to first declare the pointer to the matrix:

float **matrix;

Then start allocate memory according to user input:

matrix = (float **)malloc(nbLines * sizeof(float *));

for (int i = 0; i < nbLines; i++)
{
    matrix[i] = (float *)malloc(nbColums * sizeof(float ));
}

The segmentation fault error happens becouse you are not allocating memory for your matrix, but just a [nbL * nbCol] pointers to float

Neb
  • 2,270
  • 1
  • 12
  • 22
  • 1
    This suggests that matrices should be implemented as arrays of pointers, which is not good - it's probably better to implement matrices as dynamically allocated arrays of `float` – anatolyg Sep 25 '17 at 12:18
  • Also, in C, the type conversions of results of `malloc()` are not required (and are actively discouraged as bad technique - if `#include ` has been forgotten, the conversions obscure that AND result in undefined behaviour). It is also considered better to avoid hard-coding the type in the `malloc()` call e.g. use `matrix = malloc(nbLines * sizeof (*matrix))` rather than `matrix = malloc(nbLines * sizeof (float *))` since the latter will break if the definition of `matrix` changes ... such as to a `double **`. – Peter Sep 25 '17 at 12:32
1

You don't allocate enough memory for your array, thus you invoke Undefined Behavior, since you go out of bounds, causing a Segmentation fault.

You could declare it like a 2D array, like this:

/* TODO: Check if allocation succeeded. (check for NULL pointer) */
float** matrix;
matrix = malloc(nbLines * sizeof(float*));
for(int i = 0 ; i < N ; i++)
    matrix[i] = malloc(nbColumns * sizeof(float));

I have other approaches for allocating a 2D array dynamically here.

Please note: Do I cast the result of malloc? No!

Also do not forget to free().


You could emulate a 2D array with an 1D array, like this:

void enterMatrix(float* matrix, int nbLines, int nbColumns){
    for (int i = 0; i < nbLines ; i++) {
        for (int j = 0; j < nbColumns; j++) {
        scanf("%f", matrix[i + nbColumns * j]);
    }
}
float matrix[nbLines * nbColumns];
gsamaras
  • 71,951
  • 46
  • 188
  • 305
1

You're creating a variable length array, and, of pointers.

While other answers are perfectly valid, if you really want a 2D array, you just need to change the declaration:

float matrix[nbLines][nbColumns];

to declare a 2D variable length array of floats.

Now the hard point is to pass this VLA to a function and preserve dimensions.

For that you could use C99 way of passing VLAs (note that dimensions must be located before the VLA itself). Reference: Passing a multidimensional variable length array to a function:

void enterMatrix(int nbLines, int nbColumns, float matrix[][nbColumns] ){
    for (int i = 0; i < nbLines; i++){
       for (int j = 0; j < nbColumns; j++)
   {            
        scanf("%f", &matrix[i][j]);
    }
  }
}

call as follows:

    enterMatrix(nbLines, nbColumns, matrix);
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219