-1

I'm doing a project for school and they force us to use a type float triple pointer in a function that multiply two matrices, and for the last day i can't figure out why when I'm using int triple pointer I get the numbers needed but when I'm using float I get zeros. I wrote something simple just for example for the problem. Thank you !!

    int ***ptr3;
    int Matrix[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
    int i;

    ptr3 = malloc(sizeof(int));
    ptr3 = Matrix;
    for (i = 0; i < 9; i++) {printf_s("%d ", ptr3[i]);}


    printf_s("\n");


    float ***ptr3_f;
    float Matrix_f[3][3] = { {1,2,3},{4,5,6},{7,8,9} };

    ptr3_f = malloc(sizeof(float));
    ptr3_f = Matrix_f;
    for (i = 0; i < 9; i++) {printf_s("%.1f ", ptr3_f[i]);}

enter image description here

3 Answers3

1

There is a whole lot of misconceptions here and your teacher does unfortunately not seem to know C very well. You simply can't use a type*** and it doesn't make any sense to use either.

  • A pointer of the type type*** cannot point at a 3D array of type. Nor can it point at a 2D array. It cannot point at any array type at all.

    Sometimes when using dynamic memory allocation, we allocate an array of type*, each pointing at the first item in an array. A type** can then be used to point at the first type* element, to emulate the syntax of a 2D array with [i][j] access.

    This does however not magically make the array of type* an array type[] at the same time. Nor does it magically make type** an array type[][]. If someone taught you that, they are confused.

    Most of the time, we should not use type** to emulate a 2D array in the first place, because doing so is horribly inefficient. See Correctly allocating multi-dimensional arrays.

  • Thus when you attempt ptr3 = Matrix;, you get a C language constraint violation error by the compiler. Some lax compilers "only" give you a warning, but that doesn't make the code valid C. The type*** cannot be used to point at a 3D array, period.

    If you somehow got the correct output in some scenario, that's by luck, since the behavior of your code isn't well-defined. On some system, int happened to have the same size as the pointer or such.

  • ptr3 = malloc(sizeof(int)); ptr3 = ... is senseless, since all that you achieve with the malloc is a memory leak. Because the first thing you do is to overwrite the pointer address to the data you just allocated. I'm not sure why you want to allocate a single int to begin with.

Getting rid of all misconceptions, you can perhaps salvage the program in the following manner:

#include <stdio.h>
#include <stdlib.h>

int main (void)
{

  int (*iptr)[3];
  int imatrix[3][3] = { {1,2,3},{4,5,6},{7,8,9} };

  iptr = imatrix;
  for (int i=0; i<3; i++)
  { 
    for (int j=0; j<3; j++)
    {
      printf_s("%d ", iptr[i][j]);
    }
    printf("\n");
  }

  printf("\n");

  float (*fptr)[3];
  float fmatrix [3][3] = { {1.0f,2.0f,3.0f},{4.0f,5.0f,6.0f},{7.0f,8.0f,9.0f} };

  fptr = fmatrix;
  for (int i=0; i<3; i++)
  { 
    for (int j=0; j<3; j++)
    {
      printf_s("%.1f ", fptr[i][j]);
    }
    printf("\n");
  }
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
0

Did you see the warning when you compile your code:

warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]

warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int **’ [-Wformat=]
assignment from incompatible pointer type [-Wincompatible-pointer-types]

warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘float **’ [-Wformat=]

You can do something like:

ptr3 = malloc(sizeof(int**)); // allocate the memory for storing one double pointer
*ptr3 = malloc(sizeof(int*)); // allocate the memory for storing one single pointer
**ptr3 = Matrix[0]; // point to first row of the matrix

// it's similar to float pointer type
ptr3_f = malloc(sizeof(float**)); 
*ptr3_f = malloc(sizeof(float*)); 
**ptr3_f = Matrix_f[0];

Then when you want to print:

for (i = 0; i < 9; i++) {printf("%d ", (**ptr3)[i]);}
for (i = 0; i < 9; i++) {printf("%.1f ", (**ptr3_f)[i]);}
Hitokiri
  • 3,607
  • 1
  • 9
  • 29
  • Well it can be done without pointers too :D OP has this condition: _"I'm doing a project for school and they force us to use a type float triple pointer in a function that multiply two matrices"_ – P0W Jun 01 '20 at 09:19
  • @P0W i did not do the attention. sorry about that – Hitokiri Jun 01 '20 at 09:20
  • And just what is all this pointer goo useful for? That's just obfuscation. They already allocated the array statically. You aren't doing the OP any favours by telling them to stick to the "three star programming" pattern... – Lundin Jun 01 '20 at 09:48
  • @Lundin infact, we can use a single pointer or pointer to an array as your answer, but the OP have to use triple pointer ( `they force us to use a type float triple pointer`), so i just propose one way with the triple pointer, his code can work. – Hitokiri Jun 01 '20 at 09:56
  • @Hitokiri So if your carpentry teacher forces you to build a cabin but hands you a rotten banana instead of hammer, you should go ahead and build it anyway? Even when it becomes obvious that your teacher themselves have never built a cabin in their whole career? – Lundin Jun 01 '20 at 10:05
0

You don't need triple pointer for such arrays.

With:

#include <stdio.h>

#include <stdlib.h>

int main()
{

    int *ptr3_i;
    int Matrix[3][3] = { {1,2,3},{4,5,6},{7,8,9} };

    float *ptr3_f;
    float Matrix_f[3][3] = { {1,2,3},{4,5,6},{7,8,9} };

    int i;

    ptr3_i = (int *)Matrix;
    printf("ptr3_i:");
    for (i = 0; i < 9; i++) 
        printf("%d ", ptr3_i[i]);
    printf("\n");

    ptr3_f = (float *)Matrix_f;
    printf("ptr3_f:");
    for (i = 0; i < 9; i++) 
        printf("%.1f ", ptr3_f[i]);
    printf("\n");

    return 0;
}

I get:

ptr3_i:1 2 3 4 5 6 7 8 9 
ptr3_f:1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 
pifor
  • 7,419
  • 2
  • 8
  • 16
  • Can you give a compiler version and compiler flags that say it's a invalid pointer conversion ? I cannot with gcc 7.5.0 and '-Wall -pedantic -std=c11` – pifor Jun 01 '20 at 10:03
  • I can't, because the code is wrong and you silence the compiler with the cast, which means "hush, I (don't) know what I'm doing here". You could do `ptr3_i = &Matrix[0][0];` though, but strictly speaking I don't think it is well-defined to iterate beyond the first `int[3]` array with that pointer. – Lundin Jun 01 '20 at 10:07
  • That is, the C language allows any explicit pointer conversion from any object pointer to another object pointer (C11 chapter 6.3.2.3 regarding pointer conversions). Problems may only arise when you de-reference the pointer through a different type, in run-time. Then all manner of bugs are allowed to explode, such as invalid conversion signals, instruction traps, misalignment, aliasing violations etc etc. The compiler can't help you with run-time bugs. The OS is free to give a SIGSEGV upon executing this code, as far as C is concerned. What a specific OS actually does is another story. – Lundin Jun 01 '20 at 10:14