【问题标题】:How can I merge two arrays declared as void pointers?如何合并两个声明为 void 指针的数组?
【发布时间】:2014-06-18 16:07:22
【问题描述】:

我目前有我正在编写的程序,我正在实现一个数组的合并排序。该数组包含未知变量——它是一个 void 指针,所以我实际上不知道我在排序什么类型的对象(有一个比较函数传入用于实际比较)。

当它是一个空指针时,我如何遍历数组?我了解到我不能只使用典型的数组格式(即arr[3]),因为它是一个空指针。有一个参数传递到我的函数中,它保存了神秘元素的大小,所以我想我需要它。有没有办法可以根据提供的大小进行转换,这样我就可以使用典型的数组格式,还是必须使用指针算术(再次,必须以某种方式将其转换为提供的大小)?

感谢任何提供意见的人! :)

【问题讨论】:

  • 你为什么要删除你的代码>.>

标签: void-pointers


【解决方案1】:

有一个参数传递到我的函数中,它保存着神秘元素的大小

很好——这正是你需要做的正确的指针算术。这与qsort 库函数使用的方法相同。

void merge_sort(void *array, size_t N, size_t size, int (*compare)(const void *, const void *));

void* 指针转换为char* 后,您将能够计算神秘元素i 的位置,如下所示:

size_t size; // Element size
void *array; // The address of the array
size_t N;    // Count of elements in the array
char *base = array;
for (int i = 0 ; i != N ; i++) {
    void *elementAtPositionI = &base[i * size];
    ...
}

要找到拆分数组以分别排序的点,您可以使用相同的技术:

void *secondHalf = &base[N * size / 2];

虽然我不能让它工作......似乎我正在跳过值并通过数组进入内存!

您的代码中仍存在几个主要问题:

  • 您的代码跳过了值,因为您错误地计算了左右部分的大小:您假设它们都是num_elem/2,而实际上其中一个是num_elem/2+1,而num_elem 是奇数。左侧使用num_elem/2,右侧使用num_elem-num_elem/2。找出所有做出假设的地方,并修正它们(不止一个地方)。
  • 您的代码进入了错误的内存,因为您计算了不正确的中间位置。您需要修复此行:merge(carr, carr + (num_elem/2) /* <<== HERE */, num_elem/2, num_elem/2, elem_size, cmp);
  • 您将元素错误地复制到helper。而不是helper[helper_place * elem_size] = *a_temp;,您需要调用memcpy 并使用elem_size 作为要复制的字节数。您需要在多个地方进行此修复。

这应该会让您更接近可行的解决方案。

【讨论】:

  • 感谢您的帮助!我重写了所有代码以使用 char 指针。虽然我不能让它工作......似乎我正在跳过值并通过数组进入内存!
  • 就是这样!太感谢了。无效指针往往是我的弱点 XD 幸运的是,除此之外,我不必处理它们太多,至少在这个特定的程序中 :)
【解决方案2】:

mergesort 中,您需要将指针视为char*,您需要传递对象的大小以便知道如何正确执行指针运算。

void mergesort(void* a, void* b, size_t objectSize, size_t objectCount)
{
   char* ac = (char*)a;
   char* bc = (char*)b;

   //.....

   mergesort(ac, ac+objectSize*objectCount/2);
}

【讨论】:

  • 这是有道理的——我什至不认为我必须调整我的整个排序算法,但我必须这样做才有意义。
猜你喜欢
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-13
相关资源
最近更新 更多