带有const参数的C中的getters

时间:2017-12-29 14:44:24

标签: c pointers const

我们说我有一个功能:

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的解决方案?

3 个答案:

答案 0 :(得分:4)

2种方法:

  1. 形成t_list *get(const t_list *, ...),与标准C函数char *strstr(const char *s1, ...);非常相似,但问题类似。即使s1指向const数据并且返回的值是指向s1中元素的指针,该函数也会返回非const指针。这是C中的常见做法。

  2. 表格2 getter功能。很容易让一个人成为另一个人的包装。

    const t_list *get_const(const t_list *, ...) {
      ...
    } 
    
    t_list *get(t_list *, ...) {
      return (t_list *) get_const(t_list *, ...);
    }
    
  3. 我更喜欢#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*,但你需要决定(也许你的代码,甚至在所有的呼叫站点都要更正)......