- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我收到这条消息:
expected 'void **' but argument is of type 'char **'
当我尝试编译类似这样的东西时:
void myfree( void **v )
{
if( !v || !*v )
return;
free( *v );
*v = NULL;
return;
}
在阅读关于堆栈溢出的这个问题后,我找到了我认为是解决方案的方法:
Avoid incompatible pointer warning when dealing with double-indirection - 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;
}
这是合法的 C 吗?我正在取消引用 void 指针,不是吗?
谢谢大家
编辑美国东部时间 2010 年 12 月 10 日下午 4:45:
正如已经指出的那样,free(NULL)
是安全的并且包含在 C 标准中。此外,正如下面所讨论的,我上面的示例不是合法的 C。请参阅 caf 的答案、Zack 的答案和我自己的答案。
因此,我将更容易将任何待 malloc 的指针初始化为 NULL,然后直接在代码中将其初始化为 free() 和 NULL:
free( pointer );
pointer = NULL;
我之所以像以前那样在 myfree() 中检查 NULL,是因为我使用 fclose() 的经验。 fclose(NULL)
可能会出现段错误,具体取决于平台(例如 xpsp3 msvcrt.dll 7.0.2600.5512),所以我曾(错误地)假设 free() 会发生同样的事情。我曾想过,与其用 if 语句弄乱我的代码,不如在函数中更好地实现它。
感谢大家的积极讨论
最佳答案
不,这是不合法的 C,除非您将 void *
对象的地址传递给 myfree()
(因此您可能以及只保留您的原始定义)。
原因是在您的示例中,char *
类型的对象(在 main()
中声明为 test
的对象)是通过 void *
类型的左值修改(myfree()
中的左值 *v
)。 C 标准的 §6.5 指出:
7 An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
— a type compatible with the effective type of the object,
— a qualified version of a type compatible with the effective type of
the object,
— a type that is the signed or unsigned type corresponding to the effective
type of the object,
— a type that is the signed or unsigned type corresponding to a qualified
version of the effective type of the object,
— an aggregate or union type that includes one of the aforementioned
types among its members (including, recursively, a member of a subaggregate
or contained union), or
— a character type.
因为 void *
和 char *
不是兼容的类型,这个约束已经被打破。 §6.7.5.1 描述了两种指针类型兼容的条件:
For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
要达到你想要的效果,必须使用宏:
#define MYFREE(p) (free(p), (p) = NULL)
(不需要检查 NULL
,因为 free(NULL)
是合法的。注意这个宏对 p
求值两次) .
关于C题: single dereference on a void** double indirection pointer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4371232/
*&x 是否总是等于 x?如果不是,什么时候不是? &*x 是否总是等于 x?如果不是,什么时候不是? 我的猜测是 (1) 总是正确的,但 (2) 并不总是正确的,因为 x 可能并不总是一个指针,所以
这段代码: int main(char[][] args) { MyObject obj; obj.x; return 0; } 给我:Error: null dereference in
我想减少使用 XMLHttpRequest() 从服务器获取信息的 I/O 开销或ActiveXObject()视情况而定,通过创建一个通用函数来执行提取,然后使用 sessionStorage. 存
我对以下代码有疑问: #!/usr/bin/perl use strict; use warnings; my %dmax=("dad" => "aaa","asd" => "bbb"); my %d
int main() { char test[15] = "Hallo World"; test[1] = *"e"; } 要将第二个字母更改为 e,我必须遵循字符串 "e"。我找不到
我正在尝试通过实现一些基本数据结构来学习 Rust。在本例中,是一个 Matrix。 struct Matrix { pub nrows: uint, pub ncols: uint, p
Editor's note: This code example is from a version of Rust prior to 1.0 and is not valid Rust 1.0 co
我刚刚阅读完 rust-lang.org 上的生命周期指南并尝试实现该示例(但使用通用枚举来增加一点复杂性)。 enum PositionInfo { Position(T, T), } en
在 JavaScript 中,如何取消引用函数返回的对象? 例如: var tmp = getTextProperties(); font = tmp.font; size = tmp.siz
我是 C++ 的新手,作为练习(也许最终是 .Net 实用程序),我正在做一个指针包装器(实际上是在 C++/CLI 中,但这也适用于 C++)。这个指针包装器(称为 Apont)目前的行为就像一个指
表达式 &ptr->fld不代表取消引用,而是应将其视为 (uint32_t)ptr + offsetof (ptr, fld) .我确信 GCC 做了这种简化,但我找不到代码中的位置。 以上结果为
我现在正在试验 Rust,我真的被各种随机的编译器错误绊倒了,比如这个: error: cannot move out of dereference of `&`-pointer return
我是 Rust 的新手,正在尝试编写命令行实用程序作为学习的一种方式。 我正在获取 args 的列表并尝试匹配它们 let args = os::args() //some more code mat
我目前正在为 C 语言开发一个简单的克隆检测器,用 C++ 编写,并且不断地问自己关于效率和如何优化 C++ 代码的问题。 我有一个问题是关于如何有效地传递结构。如果给出类似于以下内容的结构: typ
我在 C# 中有一些代码使用这样的结构: ArrayList addrs = new ArrayList(); byte[] addr = new byte[8]; while (oneWire.Se
这个问题在这里已经有了答案: What's the meaning of * and & when applied to variable names? (1 个回答) 关闭 6 年前。 刚接触 C
在 boost::filesystem 中,path 类总是尝试解引用符号链接(symbolic link)。许多 API 都是为了让符号链接(symbolic link)看起来不可见。我猜他们下面的
我正在尝试使用 C# 委托(delegate)实现撤消功能。基本上,我有一个 UndoStack,它维护一个实现每个撤消操作的委托(delegate)列表。当用户选择 Edit:Undo 时,此堆栈弹
我有一个工作正常的记录器,但在内存分配方面产生了相当多的开销。下面的 Debug() 函数不是故意打印的,因为 logOutputLevel 不够高。 var logOutputLevel = 2 f
我有这个 C 代码: #include #include
我是一名优秀的程序员,十分优秀!