C-我应该在Visual Studio中投入void **



我用Visual Studio 9.0(2008)编译了一些代码。

表现为预期,但是当我用手工分配一些2D数组函数,视觉模拟生成一些C4133警告:

void ** alloc_2d(int w, int h, size_t type_size);
void free_d2(void ** mem);
int main (void)
{        
    float ** data;
    /* Here is generated a C4133 warning:
       "incompatible type from void ** to float **" */
    data = alloc_2d(100, 100, sizeof **data);
    /* do things with data */
    /* free data */
    free_2d(data);
    return 0;
}

我明白为什么会产生此警告,但我想知道我该怎么做才能使其保持安静。

我该怎么办?

  • 与警告一样?
  • 禁用警告(我认为危险)?
  • 禁用围绕alloc_2d调用的警告(具有特定于某些宏Visual Studio)?
  • 施放功能返回(但是[我施放了malloc的结果吗?)

第二个问题:

  • 较新的/其他编译器是否知道这种演员?

void**背后是隐藏的两个阵列:一个很大的用于存储我需要连续的所有数据,而另一个可以通过不同的行浏览。

实现看起来像(我删除了错误检查)

void **alloc_2D_array(int w, int h, size_t size)
{
    void ** mem = malloc(w * sizeof *mem);
    *mem = malloc(w*h*size);
    for (i = 1; i < w; ++i)
    {
        mem[i] = (void*)((char*)mem[0] + i*w*size);
    }
    return mem;
}

从签名中,我认为您的功能大致像这样实现了(另外,错误检查我在这里留在这里以换取简洁):

void **alloc_2d(int w, int h, size_t type_size)
{
    void **pointers = malloc(h * sizeof *pointers);
    for (size_t i = 0; i < h; ++i)
    {
        pointers[i] = malloc(w * type_size);
    }
    return pointers;
}

对此发表了一些评论:

  • 此功能的结果是不是 a 2D数组,而是数组的数组。它可以与真实的2D阵列相似,但带有一些开销。真正的2D数组将是一个大小w * h * type_size的连续块。
  • 实际上,此代码实际上是不安全的,当您将void **从其返回到float **时,可以调用不确定的行为。这是因为不能保证指向不同类型的指示具有相同的表示形式 - 它们甚至可以具有不同的大小。另请参阅是否有任何平台,指向不同类型的指针具有不同的尺寸?通过将void **施放到float **,您正在对待void * 的数组,就好像它是float *的数组一样。尽管在您典型的现代PC平台上可能还不错,但此可以完全错误

也就是说,您可以通过简单地将函数返回void *而不是void **来避免演员,但这只会隐藏问题:void * IS generic指针类型,编译器将允许隐式转换对于任何其他指针类型,但是您仍然使用错误的指针类型访问void *数组。


我建议改为分配一个平面阵列,然后手动计算偏移量,例如:

size_t rows = 100;
size_t cols = 100;
float *data = malloc(cols * rows * sizeof *data);
data[cols*5 + 3] = 1.41;
// ...
free(data);

作为替代方案,您可以使用可变长度阵列(C99中的强制性,可选,但在C11中几乎总是支持Microsoft ....)来动态分配真实 2D数组

size_t rows = 100;
size_t cols = 100;
float (*data)[cols] = malloc(rows * sizeof *data);
data[5][3] = 1.41;
// ...
free(data);

C中的通用指针类型为void*。这确实不是表示void**也是一种通用指针类型,该规则不递归适用。

相反,从void**转换为float**或相反的转换是无效的指针转换。它们不是兼容类型 - 编译器必须发出诊断消息。忽略警告可能会导致数据错位或严格的混溶问题 - 在任何一种情况下。


我该怎么办?

修复代码,以使其不包含禁止的指针转换。


较新的/其他编译器是否意识到这种演员?

自第一个标准化c。

以来,此特定规则没有改变

至于如何修复代码...您不应该。您应该从头开始重写,以便分配 arrays ,而不是"基于指针的查找表"。没有明显的理由为什么您会从这里的查找餐桌中受益,但是您应该避免它的原因很多。

此外,如果您使用指针到VLA。

,您的代码将更加可读。

请参阅正确分配多维数组,以获取如何执行此操作的示例(在答案的底部,代码示例)。

相关内容

  • 没有找到相关文章

最新更新