在最近的讨论中(请参阅this answer的注释),R ..建议永远不要为指针到const
类型创建别名,因为您将无法轻松释放引用的对象在一个符合C的程序中(请记住:free()
采用非const
指针参数和C99 6.3.2.3只允许从非限定转换为限定。
C语言显然假定任何已分配对象的所有者存在,即某人必须存储指向该对象的非const
指针,并且该人负责释放。
现在,考虑一个库分配和初始化从用户空间代码不可修改的对象,因此函数调用总是返回const
- 限定指针。
显然,库是对象的所有者,并且应该保留非const
指针,这有点傻,因为用户已经提供了完全有效但指针的const
副本每个图书馆电话。
要解除分配此类对象,库必须放弃const
限定符;据我所知,以下
void dealloc_foo(const struct foo *foo)
{
free((void *)foo);
}
是有效的C;如果foo
参数另外restrict
- 合格。
然而,抛弃const
似乎有些骇人听闻。
除了从库函数的所有返回值中删除const
之外还有另一种方法,它会丢失有关对象可变性的任何信息吗?
答案 0 :(得分:4)
我在6.3.2.3中没有读到相同的内容。该段是关于隐式发生并且不需要演员表的转换。因此,可能不允许从指针到const
对象的隐式转换,但这并未说明显式转换。
在6.5.4中处理了强制转换,我没有看到任何会限制你从任何指向const
的强制转换的东西,而const
本身不是(void*)
符合{{{} 1}}。相反,它说
涉及指针的转化, 除了允许的地方 的约束 6.5.16.1,应通过明确的演员表明。
所以我读到那里,如果你明确地做事,他们是允许的。
所以我认为以下是完全有效的
char const *p = malloc(1);
free((void*)p);
<德尔>
6.5.4 forbits将是以下内容
char * const p = malloc(1);
自由((无效*)P); / *的表达式是const限定的* /
德尔>
作为旁注,对于你的第二个想法,一个库返回一个指针到const
限定的对象然后被置于调用者的责任中,对我来说没什么意义。任
const
指向弱点”
保护,呼叫者不
改变它,或const
指针,用于
他的用途。答案 1 :(得分:2)
如果对象真的是不可变的,为什么要给用户指向它的对象并冒险成为腐败对象的机会?将对象地址保留在表中,向用户返回一个不透明句柄(整数表索引?)并接受库例程中的句柄。
答案 2 :(得分:1)
如果返回const
- 限定指针,则语义是不允许函数的调用者以任何方式修改对象。这包括释放它,或将它传递给你的库中的任何功能,而这些功能将反过来释放它。是的我知道你可以抛弃const
限定符,但是你违反了const
暗示的合同。