【问题标题】:warning: ISO C++ forbids variable length array警告:ISO C++ 禁止变长数组
【发布时间】:2018-11-16 07:00:16
【问题描述】:

我有一个函数,它接受一个指向浮点数组的指针。根据其他条件,我知道指针实际上指向的是 2x2 OR 3x3 矩阵。 (实际上内存最初是这样分配的,例如 float M[2][2] )重要的是我想在函数体中做出这个决定,而不是作为函数参数。

void calcMatrix( int face, float * matrixReturnAsArray )
{
    // Here, I would much rather work in natural matrix notation
    if( is2x2 )
    {
        // ### cast matrixReturnAsArray to somethingAsMatrix[2][2]
        somethingAsMatrix[0][1] = 2.002;
        // etc..
    }
    else if(is3x3)
    { //etc...
    }

}

float (somethingAsMatrix)[2] = (float ()[2]) matrixReturnAsArray; 

这很好用。

如果我想在下标中提及值作为变量,该变量将根据某些条件而变化。

如果我这样做,它会显示警告:ISO C++ 禁止可变长度数组。从这里我怎样才能动态地创建一些东西?

【问题讨论】:

  • 使用 std::vector。
  • 请填写一些缺失的代码,我认为您甚至没有显示出现错误的行。
  • 呃...“这很好用”?什么是(float ()[2]),什么编译器使它“工作正常”?这甚至不会编译。
  • 我会使用 typedef,它让事情变得容易多了。类似 typedef float twoByTwo[2][2];我已经尝试过了,但我认为它会起作用。
  • @NeilButterworth std::vector 在这种情况下是一个错误的工具。

标签: c++ arrays matrix multidimensional-array casting


【解决方案1】:

你可以通过引用传递一个数组。

void calcMatrix(float (&matrix)[2][2])   // Only binds to 2*2 matrix
{
}
void calcMatrix(float (&matrix)[3][3])   // Only binds to 3*3 matrix
{
}

int main()
{
   float a[2][2] ={{1,2} , {3,4}};
   calcMatrix(a); 

   float b[3][3] ={{1,2,3} , {4,5,6}, {7,8,9}};
   calcMatrix(b); 
}

如果您想要一个适用于不同大小的函数,您可以对其进行模板化:

template<int S>
void calcMatrix(float (&matrix)[S][S])   // Only binds to S*S matrix
{
}

【讨论】:

    【解决方案2】:

    下面展示了如何进行强制转换。

    #include <stdio.h>
    
    typedef float t2[2][2];
    typedef float t3[3][3];
    
    static void test(int is2, void * p)
    {
        if(is2)
        {
            t2 *a = (t2 *)p;
            (*a)[1][1] = 1.23;
        }
        else
        {
            (*((t3*)p))[1][1] = 2.34;
        }
    }
    
    int main()
    {
        printf("Hello World\n");
        t2 test2 = {{1,2},{3,4}};
        t3 test3 = {{1,2,3},{4,5,6},{7,8,9}};
    
        test(1,(void *)test2);
        printf("%g\n",test2[1][1]);
    
        test(0,(void *)test3);
        printf("%g\n",test3[1][1]);
    
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      C++ 中的数组必须在编译时定义一个大小。

      如果您想要变长数组,请改用std::vector

      在您的情况下,我会使用 Matrix Size 模板并针对不同的矩阵大小使用不同的实现(除非我误解了您的意图)。

      template<int SIZE> 
          struct Matrix {
          std::array<std::array<float, SIZE>,SIZE> m;
          std::array<float,SIZE>& operator[](int a) {
              if(a>=SIZE) {
                  throw std::out_of_range("Out of range exception");
              }
              return m[a];
          }
      };
      
      template<int SIZE>
      void calcMatrix(Matrix<SIZE>& matrixReturnAsArray );
      
      
      template<>
      void calcMatrix<2>(Matrix<2>& matrixReturnAsArray )
      {
           // Code for 2x2 Matrix
          std::cout << "<2>" << std::endl;
          std::cout << matrixReturnAsArray[1][1] << std::endl;
      }
      
      template<>
      void calcMatrix<3>(Matrix<3>& matrixReturnAsArray )
      {
           // Code for 3x3 matrix
              std::cout << "<3>" << std::endl;
              std::cout << matrixReturnAsArray[2][2] << std::endl;
      }
      
      int main() {
         std::array<float,2> a={1,2};
         Matrix<2> m2;
         m2.m = {a,a};
         std::array<float,3> b={1,2,3};
         Matrix<3> m3;
         m3.m = {b,b,b};
         calcMatrix(m3); 
         calcMatrix(m2);
      }
      

      由于我没有定义通用模板,使用 2 或 3 以外的任何其他值作为 size 都会导致编译时出错。

      编辑: 在@Caleth 的建议之后使用对 std::array 的引用而不是指针

      编辑 2: 添加运算符 [] 以便于访问和例外以确保安全

      【讨论】:

      • 您甚至可以将matrixReturnAsArray 声明为float(&amp;matrixReturnAsArray)[SIZE][SIZE] 以帮助扣除
      • 你是对的。虽然如果我必须在 C++ 中使用它,我可能会使用 std::array 来代替。
      • 我的意图是改变这个“float (somethingAsMatrix)[2] = (float ()[2]) matrixReturnAsArray;”。实际上它会为somethingAsMatrix(p×2)创建matrixReturnAsArray(1D)。
      • 但是在上面的评论中,如何动态地在下标中提及值?
      • 可以使用模板类型推断。您不需要转换值。让您的编译器为您完成这项工作。
      猜你喜欢
      • 1970-01-01
      • 2012-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-22
      • 1970-01-01
      相关资源
      最近更新 更多