我正在处理旧的代码库,而且几乎每次调用free()都会在其参数上使用强制转换。例如,
free((float *)velocity);
free((float *)acceleration);
free((char *)label);
其中每个指针都是相应的(和匹配的)类型。我完全没有理由这样做。这是一个非常古老的代码,所以我想知道它是不是K& R的东西。如果是这样,我实际上希望支持可能需要这个的旧编译器,所以我不想删除它们。
是否有使用这些演员表的技术理由?我甚至没有看到使用它们的实用理由。在释放数据类型之前提醒自己的重点是什么?
编辑:此问题不是另一个问题的副本。另一个问题是这个问题的一个特例,如果亲密选民能够阅读所有答案,我认为这是显而易见的。
Colophon:我正在给出" const答案"选中标记,因为这可能是为什么需要这样做的真正原因;然而,关于它是一个ANSI C之前的习惯(至少在一些程序员中)的答案似乎是它在我的情况下使用的原因。很多人在这里有很多好处。感谢您的贡献。
答案 0 :(得分:168)
如果指针为const
,则可能需要强制转换才能解析编译器警告。下面是一个代码示例,该代码在不转换free参数的情况下导致警告:
const float* velocity = malloc(2*sizeof(float));
free(velocity);
编译器(gcc 4.8.3)说:
main.c: In function ‘main’:
main.c:9:5: warning: passing argument 1 of ‘free’ discards ‘const’ qualifier from pointer target type [enabled by default]
free(velocity);
^
In file included from main.c:2:0:
/usr/include/stdlib.h:482:13: note: expected ‘void *’ but argument is of type ‘const float *’
extern void free (void *__ptr) __THROW;
如果使用free((float*) velocity);
,编译器会停止抱怨。
答案 1 :(得分:60)
预标准C没有void*
但只有char*
,因此您必须投射所有传递的参数。如果你遇到古老的C代码,你可能会发现这样的演员阵容。
Similar question with references
当第一个C标准发布时,malloc和free的原型从char*
变为今天仍然拥有的void*
。
当然,在标准C中,这样的演员表是多余的,只是危害可读性。
答案 2 :(得分:33)
这是一个免费在没有演员表的情况下失败的例子:
volatile int* p = (volatile int*)malloc(5 * sizeof(int));
free(p); // fail: warning C4090: 'function' : different 'volatile' qualifiers
free((int*)p); // success :)
free((void*)p); // success :)
在C中,您可以收到警告(在VS2012中获得警告)。在C ++中,你会收到一个错误。
除了罕见的情况外,演员阵容只会使代码膨胀......
修改强>
我转而void*
而非int*
来演示失败。它将与int*
隐含地转换为void*
的工作方式相同。添加了int*
代码。
答案 3 :(得分:30)
原因:1。通过使用<audio>
,代码明确指出应将指针视为play()
调用的一部分的类型。当free((sometype*) ptr)
替换为(自己动手)free()
时,显式强制转换非常有用。
free()
DIY_free()
是一种方法,特别是在调试模式下,对被释放的指针进行运行时分析。这通常与#define free(ptr) DIY_free(ptr, sizeof (*ptr))
配对以添加声望,全局内存使用计数等。我的小组在出现更多现代工具之前使用了这种技术多年。它必须将自由项目转换为最初分配的类型。
现代:避免Manos Nikolaidis@和@egur处理的DIY_free()
和DIY_malloc()
警告。我想我会注意到3个限定符的效果:const
,volatile
和const
。
[edit]每@R.. comment
添加了volatile
restrict
答案 4 :(得分:16)
这是另一种替代假设。
我们被告知该程序是在C89之前编写的,这意味着它无法解决与free
原型的某种不匹配问题,因为不仅没有const
这样的事情。在C89之前{1}}也不是void *
,在C89之前没有函数原型这样的东西。 stdlib.h
本身就是委员会的一项发明。如果系统标题根本无法声明free
,那么他们就会这样做:
extern free(); /* no `void` return type either! */
现在,关键在于缺少函数原型意味着编译器没有参数类型检查。它应用了默认参数提升(仍然适用于可变参数函数调用的那些),就是这样。使每个呼叫站点的参数与被呼叫者的期望一致的责任与程序员完全。
然而,这仍然并不意味着必须在大多数K&amp; R编译器上将参数转换为free
。像
free_stuff(a, b, c)
float *a;
char *b;
int *c;
{
free(a);
free(b);
free(c);
}
应该已经正确编译。所以我认为我们在这里得到的是一个程序,用于处理异常环境中的错误编译器:例如,sizeof(float *) > sizeof(int)
和编译器不会1}的环境em>对指针使用适当的调用约定,除非你在调用点转换它们。
我不知道有这样的环境,但这并不意味着没有这样的环境。想到的最可能的候选人被削减&#34;小C&#34; 20世纪80年代早期的8位和16位微处理器编译器。我也不会惊讶地发现早期的Crays有这样的问题。
答案 5 :(得分:9)
free只接受非const指针作为参数。因此,在const指针的情况下,需要显式转换为非const指针。