C问题:单个取消引用void**双间接指针

Ano*_*Guy 6 c type-conversion void void-pointers compiler-warnings

我收到了这条消息:

expected 'void **' but argument is of type 'char **'
Run Code Online (Sandbox Code Playgroud)

当我尝试编译类似于此的东西:

void myfree( void **v )
{
    if( !v || !*v )
        return;

    free( *v );
    *v = NULL;

    return;
}
Run Code Online (Sandbox Code Playgroud)



我在堆栈溢出后阅读这个问题后发现了我认为的解决方案:
在处理双重间接时避免不兼容的指针警告 - Stack Overflow

所以我调整为这样的事情:

#include <stdio.h>
#include <stdlib.h>

void myfree( void *x )
{
    void **v = x;

    if( !v || !*v )
        return;

    free( *v );
    *v = NULL;

    return;
}

int main( int argc, char *argv[] )
{
    char *test;

    if( ( test = malloc( 1 ) ) )
    {
        printf( "before: %p\n", test );
        myfree( &test );
        printf( "after: %p\n", test );
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是合法的C吗?我解除引用无效指针不是吗?

谢谢大家


编辑12/10/2010美国东部时间下午4:45:
因为它被指出free(NULL)是安全的,并由C标准涵盖.另外,如下所述,我上面的例子不合法C.请参阅caf的答案,Zack的答案和我自己的答案.

因此,我可以更容易地将任何要成为malloc的指针初始化为NULL,然后直接在代码中直接释放free()和NULL:

free( pointer );
pointer = NULL;
Run Code Online (Sandbox Code Playgroud)

我在myfree()中检查NULL的原因与我一样是因为我使用fclose()的经验.fclose(NULL)可以根据平台进行段错(例如xpsp3 msvcrt.dll 7.0.2600.5512),因此我假设(错误地)使用free()可能会发生同样的事情.我想用if语句可以更好地在函数中实现,而不是弄乱我的代码.

感谢大家所有的好评

caf*_*caf 4

不,这不是合法void *的 C,除非您将对象的地址传递给myfree()(所以您不妨保留原来的定义)。

\n\n

原因是在您的示例中,类型的对象(在 中char *声明的对象)通过类型的左值(在 中的左值)进行修改。C 标准的 \xc2\xa76.5 规定:testmain()void **vmyfree()

\n\n
\n

7 对象的存储值只能由具有以下类型之一的左值表达式访问:

\n\n
\xe2\x80\x94 a type compatible with the effective type of the object,\n\xe2\x80\x94 a qualified version of a type compatible with the effective type of \nthe object,\n\xe2\x80\x94 a type that is the signed or unsigned type corresponding to the effective\ntype of the object,\n\xe2\x80\x94 a type that is the signed or unsigned type corresponding to a qualified\nversion of the effective type of the object,\n\xe2\x80\x94 an aggregate or union type that includes one of the aforementioned\ntypes among its members (including, recursively, a member of a subaggregate\nor contained union), or\n\xe2\x80\x94 a character type.\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

由于void *char *是不兼容的类型,因此这个限制已被打破。两种指针类型兼容的条件在\xc2\xa76.7.5.1中描述:

\n\n
\n

为了使两个指针类型兼容,两者都应具有相同的限定,并且都应是指向兼容类型的指针。

\n
\n\n

要达到你想要的效果,必须使用宏:

\n\n
#define MYFREE(p) (free(p), (p) = NULL)\n
Run Code Online (Sandbox Code Playgroud)\n\n

(无需检查NULL,因为free(NULL)是合法的。请注意,该宏计算p两次)。

\n

  • @Zack你混淆了两件事。一:将“double*”转换为“void*”(你所做的)。二:将“double*”视为“void*”——换句话说,类型双关语(他做了什么,以及未定义的行为)。 (2认同)