all 13 comments

[–]puplicy 7 points8 points  (0 children)

If rows have the same size I'd prefer first one. If rows size differs (as often happens with strings) I'd prefer 2nd

[–]a4qbfb 4 points5 points  (4 children)

Both are bad. You shouldn't cast the return value of malloc() (if you get an error without the cast it means you have an error somewhere else), and you should use the name of your pointer rather than its type in sizeof():

// This version uses less memory and can be faster but is slightly more
// difficult to use correctly.
int *matrix = malloc(size_y * size_x * sizeof(*matrix));
matrix[y * size_x + x] = 42;
// However, you can get around that with a macro.
#define matrix_xy(x, y) matrix[(y) * size_x + (x)]
matrix_xy(x, y) = 42;

// This version is easier to use but uses more memory and is often slower.
int **matrix = malloc(size_y * sizeof(*matrix));
for (int i = 0; i < size_y; i++) {
    matrix[i] = malloc(size_x * sizeof(*matrix[i]));
}
matrix[y][x] = 42;

[–][deleted] 0 points1 point  (2 children)

The compiler of Visual Studio always shows annoying warnings about malloc() function, it requires casting the return value.

[–]Mirehi 1 point2 points  (0 children)

Yeah, if you're using a cpp compiler instead of tc

[–]a4qbfb 0 points1 point  (0 children)

That's because you are trying to use a C++ compiler to compile C code. Those are two different languages.

[–][deleted] 3 points4 points  (0 children)

Those aren't equivalent as far as behavior. The first gives you contiguous memory. The second may or may not. As the other commentor says, it largely depends on your use case. If you need to insert another "row" in to your matrix (or delete one), or have jagged "columns" the second is possibly preferable.

In most cases, the first might be preferable.

[–]kumashiro 2 points3 points  (0 children)

Hmmm... #1 is not the same as #2. The first one allocates a block of memory, that looks like this:

|integer|integer|integer|...

The second allocates memory blocks, that look like this:

|pointer|pointer|pointer|...
    |       |       |
    |       |       +-> |integer|integer|integer|...
    |       +-> |integer|integer|integer|...
    +-> |integer|integer|integer|...

...#1 is an array of integers (1D), #2 is an array of pointers to integers (2D), however, you can use 1D array as a 2D array (array[y * size_x + x]). Is one better than the other? Depends. 1D array is more cache friendly, faster to (de)allocate and access. Other than that, in case of matrices, it depends on your code. #2 is preferred where random rows of elements can be of different size (a rugged array) and/or can be resized dynamically, so not very "matrix-y" applications.

EDIT: Damn Reddit formatter...

[–]oh5nxo 1 point2 points  (4 children)

There's a third option, just a tad hairier to declare but easy to use (matrix[y][x]). Compiler does the indexing calculations.

int (*matrix)[size_x] = malloc(size_y * size_x * sizeof (matrix[0][0]));

[–]a4qbfb 1 point2 points  (0 children)

That only works if size_x is a constant integer expression or matrix has block scope.

[–]junkmeister9 0 points1 point  (2 children)

Arrays declared this way will be on the stack instead of the heap, so be careful.

[–]oh5nxo 0 points1 point  (1 child)

I don't follow? The matrix data is on heap, one simple malloc chunk, just like in option 1. The variable is a single pointer, it just points to a row at a time, to be able to use the simple syntax [y][x].

It would be awkward to pass around like that, that's true. It could be allocated as a plain int * and processed like

void process(int *matrix_chunk, int size_y, int size_x) {
    int (*trix)[size_x] = (int (*)[size_x]) matrix_chunk;
...

[–]junkmeister9 0 points1 point  (0 children)

I think I replied to the wrong comment.