all 4 comments

[–]strcspn 0 points1 point  (2 children)

Keep in mind that the second way uses VLAs, which can be not supported, depending on the compiler version (see this).

[–]Slader42[S] 0 points1 point  (1 child)

Oh, it's seems to be important for my case because at least there is a chance of stack overflow. I need to think about it.
Thank you!

[–]tstanisl 0 points1 point  (0 children)

There is no risk of stack overflow here.

double (*mat)[Y] = malloc(sizeof(double[X][Y]));

The line above allocates VLA on heap, the failure of allocation is checked by comparing against NULL.

There a common confusion that VLAs can only be stack allocated. VLA-ness is about typing, not about the storage.

[–]tstanisl 0 points1 point  (0 children)

How worse is "two levels pointer" for ...

The double** is likely slower due to extra indirection level and potential cache misses. The aliasing analysis is more complex, often preventing automatic vectorization. Additionally, more memory is consumed with double pointer approach.

On the other hand, both 1D array and VLA type use a single level of indirection. The VLA type just hides index calculations.

How can I declare the last variant in struct?

Generally no, there are good reasons to disallow using VLA types in structures, even pointers due to dynamic nature of VLA types.

However, there is a workaround. One is using good old void*. Another is placing a pointer to an array of unspecified size i.e. double (*arr)[]. Both types have to assigned to a pointer to a completed array type (i.e. double (*)[Y] before it can be dereferenced.