Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在特殊情况下使用void**安全吗?还是未定义的行为?_C_Malloc - Fatal编程技术网

C 在特殊情况下使用void**安全吗?还是未定义的行为?

C 在特殊情况下使用void**安全吗?还是未定义的行为?,c,malloc,C,Malloc,我想创建一个函数,释放指针指向的内存,并将指针赋值为NULL。所以我必须将参数声明为void**一个间接指针,我知道void*对于转换指针是安全的,使用void**是未定义的行为。但我认为在这种情况下这应该没有问题。这个函数能安全地释放malloc分配的内存而不产生未定义的行为吗?请黑客提供帮助或建议更好的方法 C代码: #include <stdio.h> #include <stdlib.h> // If I use safeFree(&mac_arr);

我想创建一个函数,释放指针指向的内存,并将指针赋值为NULL。所以我必须将参数声明为void**一个间接指针,我知道void*对于转换指针是安全的,使用void**是未定义的行为。但我认为在这种情况下这应该没有问题。这个函数能安全地释放malloc分配的内存而不产生未定义的行为吗?请黑客提供帮助或建议更好的方法

C代码:

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

// If I use safeFree(&mac_arr); ,
// it will warn "Incompatible pointer types passing ' int **' to parameter of type ' void **'"
// So I used #define, don't care about this.

#define SAFE_FREE(p) safeFree((void **)&(p))

void safeFree(void ** ptr);

int main(void) {
    int *mac_arr = malloc(sizeof *mac_arr);
    SAFE_FREE(mac_arr);
    return 0;
}

void safeFree(void ** ptr){
    if (ptr != NULL && *ptr != NULL) {
        free(*ptr);
        *ptr = NULL;
    }
}
指针类型int**和void**不兼容。类型转换只是掩盖了不兼容性

您可以定义:

#define SAFE_FREE(p) ((void)(free(p), (p) = NULL))

此类代码的行为不由C标准定义

大体上,mac_arr是一个int*。参数safeFree receives是指向void*的指针。但是int*和void*是C标准定义的不兼容类型。它们可能具有不同的尺寸、对齐要求和表示形式。因此,将mac_arr的地址从int**转换为void**并将*ptr用于void*类型的左值是不可移植的

它可能在许多C实现中“起作用”

您正在考虑的SAFE_-FREE宏并不是解决指针问题的好办法。虽然它将指向对象的当前指针设置为null,但它无法影响指向同一对象的其他指针,例如链表中的链接或其他数据结构中的链接


它也不需要测试*ptr!=无效的free被指定为在传递空指针时不执行任何操作,因此您只需加倍执行已执行的测试。

可能会将其转换为void*然后转换为void**?@lan Abbott我不知道void的用途,请指定,我可以写这个吗?定义SAFE_FREEp FREEp;p=nullcast to void只是为了阻止将SAFE_FREEp的值赋给变量的任何尝试。定义SAFE_FREEp FREEp的问题;p=NULL表示当以分号终止时,它是两个语句,因此如果foo SAFE_FREEbar;无法工作的条=空;部分永远都会完成。一个常见的解决方法是define SAFE_FREEp do{FREEp;p=NULL;}而0是一个单独的复合语句,当以分号终止时。宏的表达式形式(如define SAFE_FREEp FREEp)与,p=NULL我省略了void cast和宏的语句形式,例如define SAFE_FREEp do{FREEp;p=NULL;},而0表示表达式形式可以在另一个表达式(特别是逗号表达式)中使用,而语句形式不能。表达式可以形成语句,但语句不能形成表达式-至少在标准C中不是这样。@lan Abbott谢谢你,我理解。~@Treasone另外,请注意,诸如SAFE_FREE*foo++之类的调用不能用于这些宏,因为宏对*foo++求值两次。