5

Is this code proper? Is using 2 dimensional array as 1 dimensional deprecated for some reason?

char tab1[3][3];

for(int i = 0; i < 3; i++)
    for(int j = 0; j < 3; j++)
       tab1[i][j] = (char)i;

printf("%c", ((char*)tab1)[3]); // == tab1[1][0]
user4581301
  • 33,082
  • 7
  • 33
  • 54
  • 1
    @meaning-matters I believe the asker's question is "Is `arr2d[1][0]` the same spot as `arr1d[3]` if `arr1d` is `arr2d` flattened into 1 dimension via casting?". If this is the question, you have a bug in the code, Semi__. No, no bug in code. Apologies, Semi__, I misread. – user4581301 Jan 05 '18 at 23:33
  • Unless there's some special case I don't know about, this should work just fine, but I don't know if it's considered undefined behavior. Someone more knowledgeable than me on C specifications should answer this. – Havenard Jan 05 '18 at 23:36
  • 1
    Semi__ asked the Q and then asked himself "_What do you mean_"? – Khalil Khalaf Jan 05 '18 at 23:45

2 Answers2

0

Is using 2 dimensional array as 1 dimensional deprecated for some reason?

When you use tab1 the way you have, it decays to a pointer of type char (*)[3] (a pointer to an array of 3 chars). It does not decay to char*.

You cannot use it as a char* without explicitly casting it.

Re: Is this code proper?

It's well defined since, for tab1 in your code, &tab1, &tab1[0], and &tab1[0][0] point to the same location in memory even though they are all different types.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 4
    Well he did explicitly cast it, the question is if doing this [assuming the subsequent rows are contiguous in memory] is UB or not. – Havenard Jan 05 '18 at 23:38
  • @R Sahu Yes, I know they point to the same location in memory, but wouldn't be using that sort of bad practice? Or could be wrong in any particular case? –  Jan 05 '18 at 23:44
  • @Semi__, it is poor practice but It is OK as long as you are mindful of the valid range of indices. – R Sahu Jan 05 '18 at 23:46
-1

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.

Galik
  • 47,303
  • 4
  • 80
  • 117