martin
martin

Reputation: 1139

C pointer to 2 dimensional array

I've got problems with a pointer to a two dimensional array. The pointer shall point to an array of variable size.

// create pointer to 2 dimensional array
TimeSlot **systemMatrix; // this is a global variable

In a function I want to create a new array.

void setup(uint16_t lines, uint16_t coloumns) {
    // create 2 dimensional array. size can be set here.
    TimeSlot tmpTimeSlots[lines][coloumns];

    // make the pointer point to this array
    systemMatrix = tmpTimeSlots; // WARNING
}

But when I let the pointer point to the array the compiler says "warning: assignment from incompatible pointer type". In addition, the mikrocontroller where the software shall run on gets a hard fault when accessing systemmatrix[2][5] from another function.

The variable systemMatrix is needed later when accessing the elements of tmpTimeSlots.

I tried combinations like

systemMatrix = *(*tmpTimeSlot);

and so on but none of them seem to work.

Any help is appreciated :) Thanks!

EDIT: okay problem understood and solved, thanks a lot!

Upvotes: 1

Views: 7261

Answers (5)

piokuc
piokuc

Reputation: 26204

You are trying to save a pointer to a local object (allocated on stack) and use it after it goes out of scope. This is wrong, the pointer will be invalidated after the function completes.

Also. read answers on this question: Heap allocate a 2D array (not array of pointers) to learn how to allocate a 2 dimensional array dynamically (on the heap, as oppose to stack).

Upvotes: 1

Matteo Italia
Matteo Italia

Reputation: 126927

There are several errors here.

 TimeSlot **systemMatrix;

This cannot be used to point to a C multidimensional array (as declared later); instead, it can be used to point to a vector of vectors, which is a different beast (have a look at your C book for more details on this). The point is, to point to a multidimensional array you should have a declaration like this:

 TimeSlot (* systemMatrix)[lines];

which is a pointer to a vector of length lines, that can be used to address the multidimensional array (see here for more details). Now, this requires lines to be known at compile-time, so it isn't appropriate in your case.

And even if your systemMatrix declaration was correct for the assignment you do in that function, you would be assigning to that pointer the address of memory allocated inside that function, that ceases to exist after the function exit - so your systemMatrix would become an invalid pointer as soon as setup returns.

What you need here is dynamic allocation of memory. This allows you to specify an arbitrary lifetime for that memory and to use the double bracket syntax.

First of all, you allocate a vector of pointers, as big as the number of rows you need to have (multiplied by sizeof(int *) in the call to malloc); then, you allocate the row vectors and assign each one of them to its place in the column vector. See this answer for more details on this (and other) solutions to allocate dynamically a multidimensional vector.

Don't forget to free each and every allocated vector when you don't need them anymore!

Upvotes: 2

SomeWittyUsername
SomeWittyUsername

Reputation: 18368

Your systemMatrix pointer isn't a pointer to 2D array but a double-dereferencing. You need to declare it like this: TimeSlot (*systemMatrix)[columns]; - this is the correct type for 2D-array pointer. You need, however, the columns value to be known at the place of the declaration (in C99) or constant (pre-C99).

In addition, returning a pointer to a local variable will result in dangling pointer after the function returns.

Upvotes: 4

Jens
Jens

Reputation: 72746

Two problems:

  1. You must not return a pointer to automatic storage. That storage goes out of scope once the function is left. You should use malloc() instead. Using storage that went out of scope is likely to access junk on the stack, which likely causes the hard fault. Technically this is called undefined behavior in C.
  2. Contrary to your statement, TimeSlot **systemMatrix; does not declare a two dimensional array, but a pointer to a pointer to a Timeslot. See the comp.lang.c FAQ for how to dynamically create multidimensional arrays.

Upvotes: 1

user529758
user529758

Reputation:

Two-dimensional arrays != double pointers.

You almost certainly need dynamic memory allocation for this. You also want to deep copy the contents of the array - it's a non-static local variable, so it's invalid out of its scope. You can't do TYPE arr[sz]; return arr; as a consequence.

const size_t width = 3;
const size_t height = 5;
TimeSlot tmpTimeSlot[width][height];

systemMatrix = malloc(width * sizeof systemMatrix[0]);
for (int i = 0; i < width; i++) {
    systemMatrix[i] = malloc(height * sizeof systemMatrix[i][0]);
    for (int j = 0; j < height; j++) {
        systemMatrix[i][j] = tmpTimeSlot[i][j];
    }
}

Upvotes: 6

Related Questions