0

I am trying to dynamically allocate memory for a 2D array and then access the array. I am getting the following error: error: subscripted value is neither array nor pointer nor vector

    int *student; //int student[2][5]
    int main() {
       student= (int*)malloc(10*sizeof(int));
       student[0][1] = 10; //error
       printf("student %d \n",student[0][1]); //error
       return 0;
   }
1
  • In what way is it 2D? Commented Sep 5, 2018 at 1:49

2 Answers 2

1

A 2D array is a pointer pointing to another array, so when you declare student it needs to be of the type int **.

When you initialize student, first you need to allocate memory for the outer pointer, which will be pointing to the inner array. Then allocate memory for the inner array.

  int **student; //int student[2][5]
  int main() {
   student = (int**)malloc(2 * sizeof(int *));
   student[0] = (int *)malloc(5 * sizeof(int));
   student[0][1] = 10; //error
   printf("student %d \n",student[0][1]); //error
   return 0;
  }
Sign up to request clarification or add additional context in comments.

4 Comments

That's one way to do it--the other is to declare the pointer to be a pointer to sub-array types, i.e. int (*student)[5] = malloc(2 * 5 * sizeof(int));
@LeeDanielCrocker I was trying to give OP a break down of the array memory layout. But your way is more concise and shorter definitely.
The two methods have different memory layouts. Just thought the OP should know that there are two entirely different kinds of 2D array in C.
Not only are there at least two different ways to implement two-dimensional arrays in C, but the pointer-to-pointer method ought to be discouraged. It is inefficient (more memory lookups, and memory lookups that are likely to break processor look-ahead optimizations). The variable length array method Lee Daniel Crocker shows should be favored, or, if targeting C implementations where it may not be available, then manual calculation of indices into a one-dimensional array (row*ColumnSize+column) can be used.
0

There are several ways to do this:

If you know how big the dimensions need to be at compile time, and you want the rows to be contiguous in memory, do the following:

#define ROWS 2
#define COLUMNS 5
...
int (*student)[COLUMNS] = malloc( sizeof *student * ROWS );
...
student[i][j] = some_value;

If you don't know how big the dimensions need to be at compile time, and you want the rows to be contiguous in memory, and your version of C supports variable-length array syntax (C99 or later):

size_t rows;
size_t columns;

// get rows and columns somehow

int (*student)[columns] = malloc( sizeof *student * rows ); 
...
student[i][j] = some_value;

Strictly speaking, this will invoke undefined behavior since sizeof on a VLA is evaluated at runtime, and student hasn't been initialized to point anywhere meaningful yet. However, I and others argue that this is a weakness in the wording of the language standard, and I've never had this not work as expected. But, be aware, this isn't guaranteed to work everywhere all the time.

If you don't know how big the dimensions need to be at compile time, and you need the rows to be contiguous in memory, and you don't have variable-length arrays available:

size_t rows; 
size_t columns;

// get rows and columns;

int *student = malloc( sizeof *student * rows * columns );

Yeah, this is a 1D array; you'll have to map "rows" and "columns" onto this 1D structure:

student[i * ROWS + j] = some_value;

If you don't know how big your dimensions need to be at compile time, and you don't care whether rows are contiguous or not, you can do this:

size_t rows;
size_t columns;

// get rows and columns;

int **student = malloc( sizeof *student * rows );
if ( student )
{
  for ( size_t i = 0; i < rows; i++ )
  {
    student[i] = malloc( sizeof *student[i] * columns );
  }
}
...
student[i][j] = some_value;

For the first three methods, cleanup is easy:

free( student );

For the last method, you'll have to deallocate each "row" individually:

for ( size_t i = 0; i < rows; i++ )
  free( student[i] );
free( student );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.