【问题标题】:How to declare a pointer to a 2d float matrix?如何声明指向二维浮点矩阵的指针?
【发布时间】:2023-03-11 01:03:01
【问题描述】:

我试图声明一个指向二维浮点矩阵的指针,以便我的图像数据具有动态行为,但我遇到了编译错误 C2057:预期的常量表达式。我认为必须以这种方式投射指针,但显然不是......请任何人都可以帮助我吗?谢谢!!

    //Image size input

int imheight;
int imwidth;

cout << "Please, enter image height: \n>";
scanf ("%d",&imheight);
cout << "Please, enter image width: \n>";
scanf ("%d",&imheight);

const int imheight2 = imheight;
const int imwidth2 = imwidth;

float *zArray[imheight2][imwidth2];

这是我尝试访问 zArray 的其他功能之一。我没有正确读取数据:

void LoadRIS( char* inputFileName , float** zArray, int imageHeight , int  imageWidth){

    // Load input RIS file
FILE* lRis = fopen ( inputFileName, "rb" );

// Jump to data position
for (int i = 0; i < 88; i++){       
    uchar a = getc (lRis);   
}   

// Read z array
size_t counter = fread ( *zArray , 1 , imageHeight * imageWidth * sizeof(zArray) , lRis );

//Get max value of RIS
float RISmax = zArray [0][0];
float RISmin = zArray [0][0];
for (int i=0; i<imageHeight; i++) 
{
    for (int j=0; j<imageWidth; j++)
        {
            if (zArray[i][j] > RISmax)
            RISmax = zArray [i][j];
            if (zArray[i][j] < RISmin)
            RISmin = zArray [i][j];
        }
}
std::cout<<"The max value of the RIS file is: "<<RISmax<<"\n";
std::cout<<"The min value of the RIS file is: "<<RISmin<<"\n";
Beep(0,5000);


// Close input file
fclose (lRis);

}

【问题讨论】:

  • 除了答案所说的之外,该类型是指针的二维数组,而不是指向二维数组的指针。你会想要float (*zArray)[imheight2][imwidth2];
  • 这个问题被标记为 C 和 C++,但答案不同。 C 支持可变长度数组已有一段时间了,因此可以并且应该使用float foo[r][c]; 定义小的可变长度数组。应该删除其中一个标签。

标签: c++ pointers


【解决方案1】:
const int imheight2 = imheight;
const int imwidth2 = imwidth;

它不做常量表达式。您不能创建具有此类边界的数组。您应该使用dynamic-allocationvector

【讨论】:

    【解决方案2】:

    问题是您声明了 2 个 const int 变量,但您没有为它们分配 const 值。 imheightimwidth 不是常量。

    如果你对 STL 没问题:

    std::vector<std::valarray<float> > floatMatrix;
    

    编辑:仅供参考,我在上述代码行中&gt; 之间放置的空格与我的编码风格无关。您的编译器可能会假定 &gt;&gt; 是右移运算符,而不是 2 个模板参数列表终止符。 Angew 的评论总结了这一点。

    【讨论】:

    • &gt;&gt; 的“旧”解释不是错误,C++03 就是这样定义的(尽管许多编译器支持将 &gt;&gt; 视为 &gt; &gt; 作为扩展)。首先 C++11 使这种解析合法,所以现在编译器必须在适用时将 &gt;&gt; 理解为模板终止符。
    • 鉴于它应该是一个矩阵,我会考虑使用std::valarray 而不是std::vector
    • 我想我可以把最后一句话改写得更笼统,这样我就可以避免误导任何人
    • @EricPostpischil:确实,但是在 C++ 中它们不能(还)用于指定数组的大小,这是一个问题。
    • @EricPostpischil:不,不是。问题是变量是const,但它们的值不是常量表达式,因此不能用于声明数组。这正是第一句话所说的。
    【解决方案3】:

    而不是float *zArray[imheight2][imwidth2]; 应该是:

    float **zArray = new float*[imheight2];
    
    for(int i=0; i<imheight2; i++)
    {
        zArray[i] = new float[imwidth2];
    }
    

    【讨论】:

      【解决方案4】:

      试试这个(动态分配)

      //Image size input
      
      int imheight;
      int imwidth;
      
      cout << "Please, enter image height: \n>";
      scanf ("%d",&imheight);
      cout << "Please, enter image width: \n>";
      scanf ("%d",&imwidth);
      
      float** zArray = new float*[imheight];
      for(int i=0;i<imheight;i++){
          zArray[i] = new float[imwidth];
      }
      

      当然,您需要通过以下方式释放分配:

      for(int i=0;i<imheight;i++){
          delete[] zArray[i];
      }
      delete[] zArray;
      

      希望这会有所帮助:)

      附:正如@FrankH 所说,这调用了太多news 和deletes,浪费了很多时间。更好的主意应该是一起分配 imwidth*imheight 空间。

      【讨论】:

      • 工作得很好,谢谢!顺便说一句,如何从另一个函数访问双指针 float** 的值?崩溃了
      • @Nicolai 你的意思是访问二维数组中的值?只使用 zArray[i][j] 就可以了。我想知道整个代码,你能编辑问题并粘贴你的“另一个函数”代码吗?
      • 您好,hongtao,刚刚在问题中粘贴了一个函数。我现在没有崩溃,但我无法正确读取文件并将其加载到我的 zArray
      • 哎哟。 imheight+1 调用new,没有比使用array[x][y] 语法更好的理由。容易出错的delete 循环(您没有在旁边存储“二维数组”的大小,因此需要一个全局变量......)。并非所有“技术上有效”的东西都是答案。至少,只使用 两个 new / delete[] 调用,float *tmp = new float[imwidth*imheight]; for(i=0;i&lt;imheight;i++,tmp+=imwidth) zArray[i]=tmp; ... delete[] zArray[0]; delete[] zArray 以消除“了解”delete 上的尺寸的需要。我永远不会明白为什么这个疣有这么多参考...
      【解决方案5】:

      如果您这样做,那么至少将其编码为:

      float **zArray = new float*[imheight];
      float *tmp = new float[imheight*imwidth];
      
      for(int i=0; i<imheight; i++, tmp += imwidth)
          zArray[i] = tmp;
      
      ...
      delete[] *zArray;
      delete[] zArray;
      

      这至少避免了两次以上的new / delete[] 调用。如果内存不连续,它会保留您的fread(*zArray, ...) 的功能中断(如果您通过许多new 调用来初始化它,通常不会这样)。

      一个合适的包装类只会做一个new / malloc,比如:

      template <class T> class Array2D {
      private:
          size_t m_x;
          T* val;
      public:
          Array2D(size_t x, size_t y) :
              m_x(x)),
              val(new T[x*y]) {}
          ~Array2D() { delete[] val; }
          T* operator[](size_t y) { return val + y*m_x; }
      }
      

      您仍然无法将其实例分配给float**。它仍然在堆上分配,普通的常量维数组可以在堆栈上。 float** 的额外分配的唯一优点是您不必使用乘法运算 - 而是使用单独的内存访问;这种类型的行为可以被模板化/特征化到包装类中。

      一般来说,我更支持multidimensional arrays are evil(另见https://stackoverflow.com/a/14276070/512360C++ FAQ, 16.16),但口味各不相同......

      【讨论】:

        【解决方案6】:

        您不能使用具有动态大小的数组(您的宽度和高度变量不是编译时间常数)。

        您可以使用 malloc() 或 new Operator 以动态方式分配内存。

        【讨论】:

        • 你是对的,但我认为 Nicolai 很可能使用 C++,因为可变长度数组不会导致 C 中的编译器错误 C2057。因此,这个答案对于问题。
        • cplusplus.com 的引用并不好......甚至代码示例也有问题(FreeDynamicArray 泄漏(nRows - 1)*nCols 单位的T)。在 C/C++ 中使用“动态多维数组”是不对的。坚持使用std::vector 和/或使用/实现适当的matrix 类-使用operator(int, int) 而不是[][]
        • 您对那个网站确实是正确的。我将删除链接,因为此功能可能会使人们感到困惑。但是:既然我们有了 STL,就没有人应该再学习如何使用动态内存了?! :X 每个使用 C++ 的人(尤其是在使用 C 的时候)当然应该知道处理一维或多维数组!即使你(试图)避免在你自己的代码中使用它,你迟早会被要求知道这些东西。
        • 你需要了解数组,ack;并且您需要了解 C/C++“N-D 数组”既不是数组也不是矩阵,尽管有暗示性的欺骗性语法。此外,在 C/C++ 中,“动态 N-D 数组”和“静态定义的 N-D 数组”即使具有相同的维度也无法制成兼容类型。推论:如果你需要“N-D 数组”,你真的需要一个矩阵/张量类(否则涉及的多个新/删除使处理错误非常困难......许多 try {} catch {} 块)。推测为什么 STL 不提供任何内容可能是另一个问题的好话题;-)
        • 我目前正在做一个项目,我们在其中存储 N(其中 N 在执行期间发生变化)大小为 M(不变)的向量,以防止系统在优化中返回到已访问的状态过程。这实际上是一个 NxM 值矩阵,其中行数不断变化(在执行期间添加和删除向量)。连续存储要么需要在每次大小更改时移动/复制所有值,要么需要预先分配非常大的内存块。我们使用vector-of-vectors,但这不过是一个包装好的“动态二维数组”。
        【解决方案7】:

        float *pMatrix = new float[imheight2*imwidth2];

        然后像这样访问元素

        float f = pMatrix[x + imwidth2 * y];

        【讨论】:

        • 我想你的意思是y * width + x
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多