是否有必要将传递给free()
的值转换为此代码片段中的void指针?
free((void *) np->defn);
np
为链表中的struct
, defn
为链表中的char *
。
C11: 7.22.3.3自由函数
简介
#include <stdlib.h> void free(void *ptr);
这意味着它可以接受任何类型的指针(void *
是一个泛型指针类型)。一般不需要将参数强制转换为void *
,但在
int const *a = malloc(sizeof(int));
free(a);
编译器将生成一个警告
test.c: In function 'main':
test.c:33:7: warning: passing argument 1 of 'free' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
free(a);
^
In file included from test.c:2:0:
/usr/include/stdlib.h:151:7: note: expected 'void *' but argument is of type 'const int *'
void free(void *);
^
要抑制此警告,需要强制类型转换
free((void *)a);
这取决于上下文。如果stdlib.h
包含而不是,并且我们处于C89模式,那么强制转换是必要的。这是因为:当调用作用域中没有任何原型的函数时,实参类型(在默认实参提升之后)必须与函数实现的实际形参类型匹配。
当然,一个更好的解决方案是包含stdlib.h
,并确保在调用free
时,如果没有在范围内的原型,编译器诊断功能会提醒您。
在K&R时代(甚至是第二版),在作用域中没有原型的情况下调用函数仍然是常见的做法。
另一点,到目前为止没有在任何答案中提到的是,人们有时使用const T *
来保存指向动态分配内存的归属指针。例如,如果np->defn
的类型是const int *
,那么即使包含了stdlib.h
,也必须丢弃const
。转换为void *
是实现这一目标的简单方法。
这是因为free
的原型是void free(void *ptr);
,而C不允许隐式转换从指针后面删除const
。
您确实在问题中指定了非const char *
;然而,编码员有时可能会同时使用这两种类型,并且养成了总是进行强制转换的习惯(因为除了遵守通用编码准则以避免冗余强制转换之外,没有什么不好的地方)。
从技术上讲,您不需要强制转换为(void *)
。
有人在评论中问是否有编译器在没有强制类型转换的情况下给出警告,得到的回应是"可能是一个坏的"。
在这种情况下,GCC 4.8.4似乎是坏的
usr/include/stdlib.h:483:13: note: expected ‘void *’ but argument is of type ‘const char *’
extern void free (void *__ptr) __THROW;
编译器版本:
$ gcc --version
gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
添加强制转换不会造成任何伤害,并且避免了禁用该警告的诱惑——从而错过了一个真正的错误。
不,不是。尽管这样做可能会防止编译器给出的警告错误。
free(void *);
函数free
将释放所有用malloc分配的内存。它所需要的只是malloc
返回的内存地址。所以只要np->defn
有一个malloc返回的内存值,你应该没问题。