views:

260

answers:

4

Why does the following code give me a segmentation fault?

#define MAXROWS 10
#define MAXCOLS 10
void getInput (int *data[MAXROWS][MAXCOLS]) {
  int rows, cols;
  int curRow, curCol;
  printf ("How many rows and cols?");
  scanf ("%d %d", rows, cols);

  for (curRow = 0; curRow < rows; curRow++) {
    for (curCol = 0; curCol < cols; curCol++) {
      scanf ("%d", data[curRow][curCol]);
      printf ("%d\n", *data[curRow][curCol]);
    }
  }
}

void main () {
  int data[MAXROWS][MAXCOLS];

  getInput (data);
}

It seems to be that the scanf and printf statements aren't getting the right data type passed in, but I can't work out what they should be.

How can I change it so that it works properly?

A: 

scanf accepts address of variables, not the content of it:

void getInput (int data[][MAXCOLS]) {
  int rows, cols;
  int curRow, curCol;
  printf ("How many rows and cols?");
  scanf ("%d %d", &rows, &cols);
  //scanf ("%d %d", &rows, &cols);
  for (curRow = 0; curRow < rows; curRow++) {
    for (curCol = 0; curCol < cols; curCol++) {
          scanf ("%d", &data[curRow][curCol]);
          printf ("%d\n", data[curRow][curCol]);
        }
    }
}
Am
Nope, that doesn't work
Joe Bloggs
I ran it and it works for me. What is the error now?There were 4 fixed in the function above, have you done them all?
Am
+4  A: 

This declares an array of MAXROWS arrays of pointers to int.

int *data[MAXROWS][MAXCOLS];

However, in a function definition, top level arrays (of any size) are equivalent to pointers because arrays always decay to pointers to the type of the array member on passing to a function.

So your function definition is equivalent to:

void getInput (int *(*data)[MAXCOLS])

i.e. a pointer to an array of MAXCOLS pointers to int.

As your code stands, you never initialize any of the int pointers in the array, as you are passing a 2d array of ints as a pointer to a 2d array of int *.

What you probably want to pass, is a pointer to an array of MAXCOLS int:

void getInput (int (*data)[MAXCOLS])

or equivalently:

void getInput (int data[][MAXCOLS])

Then you do the following:

int main(void)
{
    int data[MAXROWS][MAXCOLS];

    getInput(data);

    return 0;
}

You are then passing your 2d array as a pointer to its first element (a pointer to a row or an array of MAXCOLS ints).

If you make sure change be sure to change:

  scanf ("%d", data[curRow][curCol]);
  printf ("%d\n", *data[curRow][curCol]);

to:

  scanf ("%d", &data[curRow][curCol]);
  printf ("%d\n", data[curRow][curCol]);

Also, check your parameters here:

scanf ("%d %d", &rows, &cols);

You need to be passing pointers to rows and cols.

Make sure to add some bounds checking to your input function so that you don't attempt to read more rows and columns than MAXROWS or MAXCOLS.

Charles Bailey
Thanks a lot for the detailed explanation and the sample code as well!
Joe Bloggs
A: 

There were a few different problems.

First, when passing arrays to functions you only need the definition of N-1 dimensions. For example if you're passing a 3D array you would put the size of the last 2 dimensions in the function sig and leave the first one empty.

foo(int threeD[][10][15]);

Second, scanf takes the address of the argument, which for your array looks like this

&data[curRow][curCol]

Third, you should always check the range of you input to make sure it's valid:

  if (rows > MAXROWS || cols > MAXCOLS) {
    printf("Bad array dimensions\n");
    return;
  }

Fourth, always compile with all warnings turned on - the compiler will warn you about allot of these things:

gcc -Wall pass_array.c -o pass_array

.

#include <stdio.h>

#define MAXROWS 10
#define MAXCOLS 10

void getInput (int data[][MAXCOLS]) {
  int rows, cols;
  int curRow, curCol;
  printf ("How many rows and cols?");
  scanf ("%d %d", &rows, &cols);

  if (rows > MAXROWS || cols > MAXCOLS) {
    printf("Bad array dimensions\n");
    return;
  }

  for (curRow = 0; curRow < rows; curRow++) {
    for (curCol = 0; curCol < cols; curCol++) {
      scanf ("%d", &data[curRow][curCol]);
      printf ("%d\n", data[curRow][curCol]);
    }
  }
}

int main () {
  int data[MAXROWS][MAXCOLS];

  getInput (data);
    return 0;
}
Robert S. Barnes
A: 

Read the FAQ on Passing array to function

Technowise