【问题标题】:Use of void pointer causes compiler warning errors使用 void 指针会导致编译器警告错误
【发布时间】:2017-07-12 21:38:18
【问题描述】:

我正在尝试创建一个分配内存并检查内存分配是否已完成的函数。为了允许分配任何内存类型,我将函数设置为接受 void,如下所示:foo(void ***memory, size_t pointer_type)。这里的意图是让用户在第一段输入任意指针,然后在第二段输入指针类型的大小来正确分配,如:

int foo(void ***memory,size_t pointer_type)
{
    void **temp;
    if((temp=calloc(10,pointer_type))==NULL)
    {
        return(-1);
    }
    for(i=0;i<10;i++)
    {
        if((temp[i]=calloc(10,pointer_type))==NULL)
        {
            // free array as can't be used
            for(i;i>=0;i--)
            {
                free(temp[i]);
                temp[i]=NULL;
            }
            free(temp);
            temp=NULL;
            return(-1);
        }
    }
    *memory=temp;
    return(0);
}

int main()
{

    double **pointer;
    if(foo(&pointer, sizeof(double))==-1)
    {
        return(-1);
    }


    //do stuff then free memory


    return (0);
}

在本例中,应创建一个双精度数组。我在阅读其他 SE 帖子时想到了这个想法,解释说这允许创建任何数组类型,但是编译器给出以下警告:

警告:从不兼容的指针类型传递 'foo' 的参数 1 注意:预期为void ***',但参数类型为'double ***'

这表明我所做的事情是不正确的,但是在分配后将数组视为双数组时,一切正常,所以我不知道该怎么做。

编辑:好的,所以使用 3 星是从一个单独的函数为 2D 数组分配内存,这就是我展示的方式,即如果我使用 pointer[a][b]=10,那么它的行为就像二维数组。如果有更好的方法,那么请举一个例子,但是我仍然要求数组是当前紧迫的任何类型。

【问题讨论】:

  • 成为 3 星 C 程序员并不是一种恭维。像void *** 这样的东西几乎总是一个糟糕的界面设计的信号。
  • @Hobojoe: void *** 不是二维(或nD)数组,也不能指向一个或以任何方式用作一个!如果你需要一个二维数组,传递一个指向一维数组的指针(指向二维数组的指针也可以,但在使用上不太直观且不符合概念)。不要太喜欢void *,如果你有一个double数组,使用double数组!
  • 记住:3-Star Programmer 不是恭维。
  • @Hobojoe:指针不是数组!相同的语法并不意味着相同的语义;它看起来像一个二维数组,但工作原理却大不相同。 SO上已经有数百个关于这个的问答,阅读它们!我有一个相关的答案here
  • 这不是“一维方法”,而是使用二维数组 - 阅读 C 中数组和指针之间的关系,这是至关重要的基础知识。指针对指针是完全不同的数据结构。两者都有其用例,但如果您需要(分配后)固定大小的矩形对象,则使用 2D 数组(也称为矩阵)。例如,您只需要一个mallocfree,这使得您的foo 完全没有必要。

标签: c arrays pointers void-pointers


【解决方案1】:

只有 void* 被认为是 void 指针,其他指针之间的转换是隐式完成的(在 C 中)。

void** 是指向void 指针的指针,它不是void 指针。这同样适用于void***

所以要修复你引用的错误改变

int foo(void ***memory,size_t pointer_type)

成为

int foo(void *memory, size_t pointer_type)

【讨论】:

    【解决方案2】:

    编译器会产生正确的警告,因为类型

    void ***
    

    与类型不同

    double ***
    

    显式转换将修复警告:

    if (foo((void ***)&pointer, sizeof(double))==-1)
    

    【讨论】:

    • 但显式转换并不能解决这可能具有未定义的行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 2017-11-03
    • 1970-01-01
    相关资源
    最近更新 更多