【问题标题】:Casting void* to char* in C在 C 中将 void* 转换为 char*
【发布时间】:2017-03-09 16:34:12
【问题描述】:

我必须为任何数据类型编写一个抽象的二进制搜索函数,并将比较函数作为参数。我不知道如何处理 void,因为不可能使用指针算术。然后我看到了标准的 qsort 函数并且确实这样做了。问题是当发生从void*char* 的转换时会发生什么?为什么会起作用?

void *bin_srch(void *a, size_t n, size_t bs, void *x, int (*cmp)(const void *a, const void *b))
{
    size_t f = 0, l = n;

    if(!n) return NULL;

    while (f < l)
    {
        size_t m = f/2 + l/2;
        char *mid = (char*)a + m*bs;

        if (cmp(x, mid) <= 0)
            l = m;
        else
            f = m + 1;
    }

    char *t = (char*)a + l*bs;

    if (!cmp(t, x))
        return t;
    else
        return NULL;
}

【问题讨论】:

  • 您不需要将任何内容转换为char * - 您的函数中的所有指针都应该是void *
  • @Someprogrammerdude 好吧,为什么是 UB? char * 可以用来访问任何其他类型,不是吗?
  • @ChrisTurner 你函数中的所有指针都应该是void * 如何对void *指针进行指针运算?
  • @AndrewHenle 指针大小相同,与类型无关,因此您可以像任何其他指针一样使用它们,即myvoidptr++
  • @ChrisTurner 我认为你犯了一个错误。您不能增加 void* 指针 - 它只是不起作用,而且即使它起作用也不清楚它会做什么 - ptr++ 将指针增加 sizeof(*ptr) 字节。这对于 void* 指针没有意义,因为 void 本身不是有效类型。

标签: c pointers casting binary-search


【解决方案1】:

它可以工作,因为char * 可以别名任何其他类型。

引自C11,第 6.3.2.3 章

[....] 当指向对象的指针转换为指向字符类型的指针时, 结果指向对象的最低寻址字节。的连续递增 结果,直到对象的大小,产生指向对象剩余字节的指针。

使用此属性,转换为char * 可以使用(转换的)指针作为操作数执行指针算术。

如同一规范中所述(我强调),第 §6.5.6/p2 章

对于加法,要么两个操作数都应具有算术类型,要么一个操作数应为 指向完整对象类型的指针,另一个应为整数类型。 (递增是 相当于加1。)

和,p3

对于减法,应满足以下条件之一:

  • 两个操作数都有算术类型;

  • 两个操作数都是指向兼容完整版本的合格或不合格版本的指针 对象类型;或

  • 左操作数是指向完整对象类型的指针,右操作数有 整数类型。

它需要指针操作数是指向完整类型的指针,void 不是,char 是。

最后,参考章节§6.2.5/p19

void 类型包含一组空值;它是一个不完整的对象类型 无法完成。

【讨论】:

    【解决方案2】:

    您基本上自己回答了您的问题。此代码包含对char * 的转换的唯一原因是在表达式中使用基于字节的指针算法,如

    char *mid = (char*)a + m*bs;
    

    即计算根据索引m 和元素bs 的字节大小指定的数组元素的位置。当您转换为 char * 时,结果指针指向与原始 void * 指针相同的位置,但现在您可以对其应用指针算术运算。

    【讨论】:

      猜你喜欢
      • 2020-10-24
      • 1970-01-01
      • 2015-12-20
      • 1970-01-01
      • 2015-12-22
      • 2021-11-30
      • 2011-10-27
      • 2016-12-28
      • 1970-01-01
      相关资源
      最近更新 更多