【问题标题】:Question about the difference between Integer triple pointer and float triple pointer关于整数三指针和浮点三指针区别的问题
【发布时间】:2020-09-19 13:24:39
【问题描述】:

我正在为学校做一个项目,他们强迫我们在将两个矩阵相乘的函数中使用类型浮点三重指针, 最后一天我不知道为什么当我使用 int 三指针时我得到所需的数字但当我使用浮点数时我得到零。 我为这个问题写了一些简单的东西。 谢谢!!

    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

【问题讨论】:

    标签: c arrays pointers matrix integer


    【解决方案1】:

    这里有很多误解,不幸的是,您的老师似乎不太了解 C。您只是不能使用type***,而且使用它们也没有任何意义。

    • type*** 类型的指针不能指向 type 的 3D 数组。它也不能指向二维数组。它根本不能指向任何数组类型。

      有时在使用动态内存分配时,我们会分配一个type* 数组,每个数组都指向数组中的第一项。然后可以使用type** 指向第一个type* 元素,以模拟具有[i][j] 访问权限的二维数组的语法

      但是不会神奇地同时使type* 的数组成为type[] 的数组。它也不会神奇地将type** 变成一个数组type[][]。如果有人教过你,他们会感到困惑。

      大多数时候,我们应该首先使用type** 来模拟二维数组,因为这样做效率极低。见Correctly allocating multi-dimensional arrays

    • 因此,当您尝试 ptr3 = Matrix; 时,编译器会收到 C 语言约束冲突错误。一些宽松的编译器“只”给你一个警告,但这并不能使代码有效 C。type*** 不能用于指向 3D 数组,句号。

      如果您在某些情况下以某种方式获得了正确的输出,那是幸运的,因为您的代码的行为没有明确定义。在某些系统上,int 恰好与指针大小相同。

    • ptr3 = malloc(sizeof(int)); ptr3 = ... 毫无意义,因为您使用 malloc 实现的只是内存泄漏。因为您要做的第一件事就是将指针地址覆盖到您刚刚分配的数据。我不知道你为什么要分配一个 int 开头。

    摆脱所有误解,您或许可以通过以下方式挽救程序:

    #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");
      }
    }
    

    【讨论】:

    • 请把这个链接分享给你的老师,他们也需要学习这些东西。
    【解决方案2】:

    此类数组不需要三重指针。

    与:

    #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;
    }
    

    我明白了:

    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 
    

    【讨论】:

    • 你能给出一个编译器版本和编译器标志,说明这是一个无效的指针转换吗?我不能使用 gcc 7.5.0 和 '-Wall -pedantic -std=c11`
    • 我不能,因为代码是错误的,并且您使用强制转换使编译器静音,这意味着“嘘,我(不)知道我在这里做什么”。虽然你可以做ptr3_i = &amp;Matrix[0][0];,但严格来说,我认为使用该指针迭代第一个int[3] 数组之外的定义并不明确。
    • 也就是说,C 语言允许从任何对象指针到另一个对象指针的任何显式指针转换(C11 第 6.3.2.3 章关于指针转换)。只有在运行时通过不同类型取消引用指针时,才会出现问题。然后各种错误都被允许爆发,例如无效的转换信号,指令陷阱,未对齐,混叠违规等。编译器无法帮助您解决运行时错误。就 C 而言,操作系统可以在执行此代码时免费提供 SIGSEGV。特定操作系统的实际作用是另一回事。
    【解决方案3】:

    您在编译代码时是否看到警告:

    警告:来自不兼容指针类型 [-Wincompatible-pointer-types] 的赋值

    警告:格式“%d”需要“int”类型的参数,但参数 2 的类型为“int **”[-Wformat=]
    来自不兼容指针类型的赋值 [-Wincompatible-pointer-types]

    警告:格式“%f”需要“double”类型的参数,但参数 2 的类型为“float **”[-Wformat=]

    你可以这样做:

    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];
    

    那么当你想打印时:

    for (i = 0; i < 9; i++) {printf("%d ", (**ptr3)[i]);}
    for (i = 0; i < 9; i++) {printf("%.1f ", (**ptr3_f)[i]);}
    

    【讨论】:

    • 好吧,它也可以在没有指针的情况下完成:D OP 有这个条件:“我正在为学校做一个项目,他们强迫我们在一个函数中使用浮点型三重指针将两个矩阵相乘”
    • @P0W 我没有引起注意。对此感到抱歉
    • 这个指针到底有什么用?那只是混淆视听。他们已经静态分配了数组。告诉他们坚持“三星级编程”模式,你并没有给 OP 带来任何好处......
    • @Lundin 事实上,我们可以使用单个指针或指向数组的指针作为您的答案,但 OP 必须使用三重指针(they force us to use a type float triple pointer),所以我只建议使用三重指针的一种方法指针,他的代码可以工作。
    • @Hitokiri 因此,如果您的木工老师强迫您建造小屋,但给您的是一根烂香蕉而不是锤子,您还是应该继续建造它吗?即使很明显你的老师自己在整个职业生涯中从未建造过小屋?
    猜你喜欢
    • 1970-01-01
    • 2016-03-27
    • 2011-09-22
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 2016-02-03
    • 1970-01-01
    • 2019-01-23
    相关资源
    最近更新 更多