C - 处理const *的函数

时间:2018-01-26 11:09:33

标签: c pointers const

我有一个在const *中搜索内容的函数。并将这样的const *返回给找到的元素。因此该函数没有改变任何东西,我实际上想要保持“const”的可读性和可重用性。 但我有另一个函数,只用一个*调用该函数,然后使用返回的值。但在这个用例中,应该更改值。但是因为返回的值是const *我不能那样做。 我应该调整我的编程模式以避开这个问题吗?

const void* search_min_vector_element(const void* vector, size_t length, size_t element_size, int(*cmp_fnc) (const void*, const void*));

这是第一个功能。

void* min_element = search_min_vector_element((unsigned char*) vector + (i * element_size), length - i, element_size, cmp_fnc);

这就是第二个电话。在这种情况下,vector无效*。因此,我想修改它。 谢谢你的帮助。

5 个答案:

答案 0 :(得分:2)

您可以根据参数的类型选择要执行的函数。编写_Generic宏来选择允许的类型,然后根据它调用适当的函数。例如:

#include <stdio.h>

char* print_str (char* str)
{
  printf("%s\n", str);
  return str;
}

const char* print_str_const (const char* str)
{
  printf("const %s\n", str);
  return str;
}

#define print(str)                       \
  _Generic((str),                        \
           const char*: print_str_const, \
           char*:       print_str) (str) 


int main(void)
{
  const char* cstr = "hello";
  char* str = "world";

  cstr = print(cstr);      // ok
  str = print(str);        // ok
  cstr = print(str);       // ok
//str = print(cstr);       // compiler error, incorrect assignment
//str = print((void*)str); // compiler error, wrong type
}

答案 1 :(得分:0)

在C ++中,你有很多选择来处理这个问题。但由于这是C,创建另一个函数是我目前可以提出的最佳解决方案:

const void* search_min_vector_element_const(const void* vector, size_t length, size_t element_size, int(*cmp_fnc) (const void*, const void*));
      void* search_min_vector_element      (      void* vector, size_t length, size_t element_size, int(*cmp_fnc) (      void*,       void*));

您也可以直接强制转换结果:

void* min_element = (void*)search_min_vector_element((unsigned char*) vector + (i * element_size), length - i, element_size, cmp_fnc);

答案 2 :(得分:0)

我真的建议将返回类型(如果可以)更改为不是常量值。这不是search_min_vector_element的业务,而是另一个函数应该对结果做什么。

如果您无法更改退货类型,则需要:

const void* value = search_min_vector_element(....)
void* second_no_const_value = *value; // copy value of the value pointed by    constant pointer.

答案 3 :(得分:0)

因为你知道你持有一个指向vector的非常量指针的事实,你应该简单地转换你收到的const指针:

void* min_element = (void*)search_min_vector_element(...);

答案 4 :(得分:0)

从技术上讲,您可以通过显式转换从const char*转换为char*,而不会产生未定义的行为本身;但是,如果您更改了一个不得更改的值(例如字符串文字),那么您将获得未定义的行为。因此const - 限定符不会禁止更改基础数据,但是当在函数参数或返回值中用作限定符时,函数原型假装该值不应被更改。

因此,如果你 - 或者一个库 - 在不知道实现的情况下提供了返回类型为const char*的函数,则不应假设返回的值指向可能被更改的内存。请参阅以下示例说明此内容。除了名称之外,函数validImpl1validImpl2具有相同的签名但不同的实现。如果您传入的参数的内容可能会被更改,则将返回值转换为第一个char*是正常的,但对于第二个,它会产生UB。因此,除非您知道函数的内部,否则不应该从const char*转换为char *

const char* validImpl1(const char* t) {
    return t;
}

const char* validImpl2(const char* t) {
    return "Hello!";
}

int main() {

    char x[100] = "Herbert";
    char* t=(char*) validImpl1(x);
    *t = 'a'; // OK
    printf("%s\n",t);

    char* t2=(char*) validImpl2(x);
    *t2 = 'a';   // Undefined behaviour here.
    printf("%s\n",t2);
}

在您的情况下,如果您是提供该功能并了解实施细节的人,您可以提供两个功能,一个使用const char*,另一个使用char*,后者只需调用前任的。所以使用你的函数的人可以依赖函数原型假装的东西。