This is fine, if for no other reason, because char
can alias all other types according to the standard. Also multidimensional arrays are allocated as a contiguous block so it is a one dimensional array in memory to begin with.
We know that tab1
decays to a pointer to the first element of a contiguous multidimensional array (which is an array) and casting that array pointer to a char*
(which can alias anything) must be fine.
If in doubt you could always do &tab1[0][0]
. Again because we know the allocated memory is contiguous.
EDIT
If this was an integer array (int tab1[3][3]
) then the story is a little different. To my understanding before C++17
the standard says that a pointer to the correct object type is valid regardless of how it obtained its value. That means casting to int*
should be fine because we know the address yielded by tab1
is the same as the address of the first element.
However after C++17
that guarantee has been removed so this cast is likely undefined behavior.
See THIS question for more details.
For that reason I would always recommend using &tab1[0][0]
which will always be valid.