c - 我应该在 Visual Studio 中投 void** 返回吗

标签 c visual-studio-2008 casting

我用 visual studio 9.0 (2008) 编译了一些代码。

行为符合预期,但是当我分配一些手工制作的二维数组时 函数,Visual-Studio 生成一些 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 )?
  • 转换函数返回(但是 [ Do I cast the result of 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;
}

对此的一些评论:

  • 此函数的结果不是一个二维数组,而是一个指向数组的指针数组。它的使用有点类似于真正的二维数组,但有一些开销。一个真正的二维数组将是 一个 大小为 w * h * type_size 的连续 block 。
  • 此代码实际上是不安全的,当您将从它返回的 void ** 转换为 float ** 时,可能会调用未定义的行为。这是因为无法保证指向不同类型的指针具有相同的表示形式——它们甚至可以具有不同的大小。另见 Are there any platforms where pointers to different types have different sizes? .通过将 void ** 转换为 float **,您可以将 void * 数组当作float * 数组。尽管在典型的现代 PC 平台上可能没问题,但这可能会完全出错

也就是说,您可以通过简单地让您的函数返回 void * 而不是 void ** 来避免强制转换,但这只会隐藏问题: 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 的支持 ....)来动态分配一个真实的二维数组:

size_t rows = 100;
size_t cols = 100;
float (*data)[cols] = malloc(rows * sizeof *data);

data[5][3] = 1.41;
// ...
free(data);

关于c - 我应该在 Visual Studio 中投 void** 返回吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61850950/

相关文章:

c++ - 我可以一次性检查一小组 boolean 值吗?

c - 从 char 数组中提取第二个和第三个值并将其转换为短(2 字节)。在 C 中

python - 使用特定的 python 导入调用 PyModule_GetDict() 时出现异常

c - 将 C/C++ 变量存储在处理器缓存中而不是系统内存中

c - 指向结构体、字段的指针莫名其妙地改变值

casting - 将堆栈对象编号转换为 int 时遇到问题 (Java)

c - 变量参数不打印

c++ - 将 C++ Win32 控制台项目类集成到 Visual Studio 2008 中的 Visual C++(Windows 窗体应用程序)项目中

visual-studio-2008 - 64 位编程和编译 - Visual Studio 2008 还是 Visual Studio 2010?

c# - VS2008中项目文件中的资源被窗体设计者创造性地得到 "reused",可以避免吗?