5

I have the following 2 typedef's:

typedef float matrix_3x4[3][4];
typedef matrix_3x4 bone_mat[128];

And the following function definition:

float ****get_bones();

Why is the following code giving me a type conversion error?

bone_mat *mat = get_bones();

Error:

error: cannot convert ‘float ****’ to ‘float (*)[128][3][4]’ in initialization
   85 |     bone_mat *mat = get_bones();
      |                     ~~~~~~~~~^~
      |                              |
      |                              float****

Tried changing the type of mat to bone_mat or bone_mat**, but shouldn't float(*)[128][3][4] be the same as float****?

Casting the return value of the function to (bone_mat*) doesn't work either.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
trxgnyp1
  • 317
  • 1
  • 10
  • 3
    Not an answer, but once you get beyond more than 2 levels of indirection, consider changing your types to nested structures and arrays thereof. It's hard to reason about a `float ****`. – pmacfarlane Jul 28 '23 at 20:42
  • 4
    Important note: ARRAYS ARE NOT POINTERS. – Mooing Duck Jul 28 '23 at 20:45
  • @pmacfarlane In this case, I did not make the `get_bones()` function. – trxgnyp1 Jul 28 '23 at 20:46
  • 2
    It may be surprising but `float****` is **not** a 4d array. – tstanisl Jul 28 '23 at 20:48
  • @tstanisl But can't it act as a pointer to a 3d one? – trxgnyp1 Jul 28 '23 at 20:50
  • 2
    No. Because dimensions of an array object are a bound its type. The `float****` has no dimensions information in it thus it is not a pointer to array even though it admits `ptr[a][b][c][d]` syntax – tstanisl Jul 28 '23 at 20:55
  • 1
    @tstanisl Think about the memory and addresses involved. `float*** *` is a pointer to a `float***`. That means that when you dereference a `float****`, you arrive at a location in memory that contains a `float***`. Not a `float`, but a pointer to another pointer. Dereference that pointer, and you arrive a location that contains a `float**`, Still not a float, but another pointer to a pointer. I could keep going. Contrast that with `float (*)[128][3][4]`, which is a pointer to a chunk of memory with `128*3*4` contiguous floats. – Brian61354270 Jul 28 '23 at 21:11
  • 2
    @trxgnyp1 Do you have access to the source code of `get_bones()`? If so, can you post it? – Andrew Henle Jul 28 '23 at 21:12
  • @Brian61354270 Your comment was probably the best explanation. I am marking the only answer as completed, but your comment is way better. The problem here is that I don't have the source code of the `get_bones()` function, and I actually know that it's supposed to return a `bone_mat*`, despite the definition. – trxgnyp1 Jul 28 '23 at 22:10

1 Answers1

2

A pointer is not an array. A pointer can point to an element of an array. float **** is a pointer to a pointer to a pointer to a pointer to float, a very unlikely object to come across in a real life project.

mat is a pointer to a bone_mat which itself is an array or 128 arrays of 3 arrays of 4 floats, a very different type of beast.

Should you post the source code to get_bones(), I would be surprised if it returns an actual float ****, I would bet it allocates memory for a bone_mat and converts the object pointer to a type inconsistent with the allocation size and block usage.

Quoting Brian61354270:

Think about the memory and addresses involved. float*** * is a pointer to a float***. That means that when you dereference a float****, you arrive at a location in memory that contains a float***. Not a float, but a pointer to another pointer. Dereference that pointer, and you arrive to a location that contains a float**, Still not a float, but another pointer to a pointer. I could keep going. Contrast that with float (*)[128][3][4], which is a pointer to a chunk of memory with 128 * 3 * 4 contiguous floats.

trxgnyp1
  • 317
  • 1
  • 10
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 1
    I do not have the source code of the function, only the definition. I am marking the answer as valid, but Brian61354270's comment explained way better. – trxgnyp1 Jul 28 '23 at 22:09