【问题标题】:Returning and casting an array pointer (Error: invalid types ... for array subscript)返回并转换一个数组指针(错误:无效类型...用于数组下标)
【发布时间】:2014-02-15 14:25:45
【问题描述】:

我发现了很多关于此的线程,但似乎没有一个有效。这可能只是一个指针问题,我需要在正确的位置放置正确数量的星星,但我无法弄清楚。

我想从最初是 3 维数组的 SQLITE 数据库中读取 blob。 Sqlite 返回一个“const void*”,我需要将其转换为一个临时表指针,以便我可以将其传输到真实表中。但我得到一个:

error: invalid types ‘unsigned char[int]’ for array subscript

当试图将值从一个表传输到另一个时。这是代码示例。

注意:以 SQL... 为前缀的函数是 SQLITE 的个人包装器,它们应该可以完美运行。

void Map::load ( void )
{
   int i, j, k;
   int errorsql;
   unsigned char *tmpmap; //[ Map_MAXDEPTH ] [ Map_MAXWIDTH ] [ Map_BYTE_WIDTH ];

   SQLactivate_errormsg();

   errorsql = SQLprepare ( "SELECT * FROM handmap;");

   if ( errorsql == SQLITE_OK)
   {
      errorsql = SQLstep ();

      if ( errorsql == SQLITE_ROW )
      {
         tmpmap = (unsigned char*) SQLcolumn_blob (1); // return the pointer to the blob

         for ( k = 0 ; k < Map_MAXDEPTH; k++ )
            for ( j = 0 ; j < Map_MAXWIDTH; j++)
               for ( i = 0; i < Map_BYTE_WIDTH; i++)
               {
                  p_map [ k ][ j ][ i ] = *tmpmap [ k ] [ j ] [ i ]; // try to copy from a table to another. Compiler fails here.
               }
      }
      else
         printf ("Map.load: Cannot step into the DB\n");

      SQLfinalize();
   }
   else
      printf ("Map.load: Cannot Prepare statement to save map into the DB\n");

   SQLdeactivate_errormsg();
}

代码很简单,它尝试从表的第一个条目中读取第 1 列(只有一个条目)。目标数组是 p_map,它是“无符号字符”的 3D 数组。但是 SQLcolumn_blob 返回一个 const void*。

所以我的想法是创建一个指向“无符号字符”的指针。然后将“const void*”转换为“unsigned char*”。然后将 unsigned char 指针用作数组。但似乎:

*tmpmap [ k ] [ j ] [ i ];

是非法的。我不能使用指针并将其重新解释为数组。这就是虽然部分,因为数组是指针,但声明不同。

感谢您的帮助。

【问题讨论】:

    标签: c++ arrays sqlite void-pointers


    【解决方案1】:

    您没有显示 p_map 的分配位置,但您说它是无符号字符的“3D”数组。如果是这样,它应该这样声明:

    unsigned char p_map[Map_MAXDEPTH][Map_MAXWIDTH][Map_BYTE_WIDTH];
    

    从您的代码的其他一些位来看,它看起来可能是char * 的数组,但这里肯定存在一些混淆:

         for ( k = 0 ; k < Map_MAXDEPTH; k++ )
            for ( j = 0 ; j < Map_MAXWIDTH; j++)
               for ( i = 0; i < Map_BYTE_WIDTH; i++)
               {
                  p_map [ k ][ j ][ i ] = *tmpmap [ k ] [ j ] [ i ]; // try to copy from a table to another. Compiler fails here.
               }
    

    我认为您是在说 tmpmap 是一个文本 blob,您希望将其完全复制到 p_map 中。最简单的方法就是:

    memcpy (p_map, tmpmap, Map_MAXDEPTH * Map_MAXWIDTH * Map_BYTE_WIDTH * sizeof(char));
    

    注意sizeof(char) 的乘法在技术上是多余的,因为它保证为 1。

    如果您尝试使用循环进行复制并且不想依赖相同的内存布局,为什么不简单:

         int z = 0;
         for ( k = 0 ; k < Map_MAXDEPTH; k++ )
            for ( j = 0 ; j < Map_MAXWIDTH; j++)
               for ( i = 0; i < Map_BYTE_WIDTH; i++)
               {
                  p_map [ k ][ j ][ i ] = tmpmap[z++];
               }
    

    【讨论】:

    • p_map 是一个对象变量,但您拥有正确的定义。 memcpy 很有趣,因为我对文本阅读功能做了同样的事情。只是我不确定 3D 数组如何对齐真实内存中的数据。我会尝试这两个。
    • 如果p_map 是一个带有虚函数的对象,memcpy-ing 是个坏主意。
    【解决方案2】:

    就目前而言,tmpmap 充当 char 的一维数组。为了使您的代码正常工作,您必须将 k、j 和 i 转换为单个数组索引。比如:

    int ind = i + (j * Map_BYTE_WIDTH) + (j * Map_BYTE_WIDTH * Map_MAXWIDTH); p_map [ k ][ j ][ i ] = tmpmap[ind];

    我想这样做。或者,您可以定义一个适当大小的 3D 数组类型,并根据该类型定义 tmpmap。现在不太明白怎么做...

    【讨论】:

    • 问题是我无法控制 SQLcolumn_blob 返回的指针类型。不过,我可以创建一个包含 3D 数组的结构,并且该函数应该返回一个指向该结构的指针。
    【解决方案3】:

    定义 tmpmap 为

    const unsigned char ( *tmpmap )[ Map_MAXWIDTH ] [ Map_BYTE_WIDTH ];
    

    如果程序是用 C++ 编写的,则更改此语句

    tmpmap = SQLcolumn_blob (1); 
    

    tmpmap = reinterpret_cast<const unsigned char ( *)[ Map_MAXWIDTH ] [ Map_BYTE_WIDTH ]>( SQLcolumn_blob (1) ); 
    

    至于错误,很明显你不能使用带有三个下标的 tmpmap,因为 tmpmap[i] 的类型是 unsigned char 并且是标量类型。

    【讨论】:

    • 啊!我懂了。我会尝试看看它是否有效。我混合使用 C 和 C++,所以我不介意使用旧方法。
    • 我在重新解释演员表中尝试了这种方法。编译成功,但结果不如预期。地图数据分散。我最终使用了 abligh 的方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 2021-12-25
    • 2021-05-30
    • 2022-09-29
    相关资源
    最近更新 更多