我们说我有一个功能:
t_list *get_first_matching(t_list *head_of_list, <some other stuff>);
此函数将从给定列表中检索元素,我可以对其进行修改。
但如果我有这样的话:
void print_matching(const t_list *head_of_list)
{
const matching_elemnt = get_first_matching(head_of_list, <other stuff>);
<print the element>
}
编译器会说我不能传递一个指向该函数的常量指针。
我能做的是复制粘贴功能,添加const:
const t_list *get_first_matching(const t_list *head_of_list, <some other stuff>);
我是否可以只使用一个与const参数一起使用的函数,并且在我需要修改检索到的元素时也能正常工作?
是否有没有警告或没有const cast的解决方案?
答案 0 :(得分:4)
2种方法:
形成t_list *get(const t_list *, ...)
,与标准C函数char *strstr(const char *s1, ...);
非常相似,但问题类似。即使s1
指向const
数据并且返回的值是指向s1
中元素的指针,该函数也会返回非const
指针。这是C中的常见做法。
表格2 getter功能。很容易让一个人成为另一个人的包装。
const t_list *get_const(const t_list *, ...) {
...
}
t_list *get(t_list *, ...) {
return (t_list *) get_const(t_list *, ...);
}
我更喜欢#2。由于const
没有出现在原始C中,解决方案#1是将const
嵌入现有代码的最佳方式。然而OP正在制作新代码,因此可以使用#2选项。
第三个样本C11方法:使用_Generic
_Generic
选择要使用的函数。必须谨慎使用 。国际海事组织_Generic
的细节仍需要工作。函数的“隐藏”对某些人来说是令人不安的,_Generic
很容易被错误地使用。请注意,下面的getnext(s)
示例评估s
两次,但一次是_Generic(s)
,编译时评估。
char *getnext_nonconst(char *s) {
return s + 1;
}
const char *getnext_const(const char *s) {
return s + 1;
}
#define getnext(s) _Generic((s), \
char *: getnext_nonconst, \
const char *: getnext_const \
) (s)
int main(void) {
char *ncs = (char []){"chux is amazing"};
ncs = getnext(ncs); // getnext_nonconst() is called
const char *cs = "but not perfect";
cs = getnext(cs); // getnext_const() is called
}
答案 1 :(得分:3)
更改现有功能以接受const
参数:
t_list *get_first_matching(const t_list *head_of_list, <some other stuff>);
这是您需要的唯一版本。当您使用非const参数调用它时,它将隐式转换为const。
答案 2 :(得分:2)
你可以(在实践中)施放第一个参数,例如
matching_elemnt = get_first_matching((const t_list *)head_of_list,
其他内容 );
但是,get_first_matching
函数(如果它是一个真正的getter函数)可能是错误的声明和定义。我觉得它的第一个参数应该是const t_list*
,但你需要决定(也许你的代码,甚至在所有的呼叫站点都要更正)......