使用void指针管理不确定类型的数组

时间:2010-10-03 01:58:05

标签: c arrays void-pointers

我正在尝试以与C的qsort函数相同的方式编写自己的Mergesort函数。如果我为一系列已知项目编写MergeSort,我就不会有问题,但是因为我不知道它们会是什么,所以它会让我失去一个循环。

我教授给出的规范不希望我使用单独的函数进行合并,所以我在Mergesort函数本身内编写了该实现。这意味着我将拥有qsort()所拥有的相同信息:

  • void* base - 指向要排序的数组的第一个元素的指针
  • size_t nel - 数组中元素的数量
  • size_t width - 每个元素的大小
  • int (*compar)( const void*, const void* ) - 一个告诉您如何比较每个元素的函数

我遇到的问题是Merge部分。我看到的每个实现都使用临时数组来存储项目,同时对它们进行排序。我不习惯使用void指针,我发现的最大障碍是移动并将值分配给数组。如何在base指向的数组中找到第二个索引处的值?如何将该数组中的值分配给临时数组?我该如何创建那个临时数组?

如果我将void指针转换为char,并将它们按宽度递增,它会工作吗?不过,我不确定作业是如何运作的。

2 个答案:

答案 0 :(得分:3)

  

如何在base指向的数组中找到第二个索引处的值?

使用(char *)base + (width*i)。这将为您提供第i个元素的地址。

  

如何将该数组中的值分配给临时数组?

您只需复制数据即可。 for (int n=0;n<width;n++) { //copy one byte from }

  

我如何创建临时数组?

类似的东西:

c - void* tempArray = malloc(width*elementsNeeded);

c ++ - void* tempArray = (void*) (new char[width*elementsNeeded]);

修改

为了进一步解释复制数据,您需要执行以下操作:

for (int n=0;n<width;n++) {
  adressTo[n] = addressFrom[n];
}
// This will copy the contents of pointer addressFrom to addressTo.

答案 1 :(得分:2)

如何在base指向的数组中的第二个索引处找到该值?如果我将void指针转换为char,并将它们按宽度递增,它会工作吗?

是的,没错。 char的大小由标准定义为1,因此根据定义,您给出的“宽度”是字符中每个元素的大小。所以你可以找到如下地址:

void *second_element_ptr = ((char*)base) + width;

你找不到,因为你不知道它的类型,所以你无法理解它占用的内存。但是没关系,使用这个接口对C中的对象进行排序,你不需要知道它们的值:你需要指向它们的指针,你可以将它们传递给比较器函数,并且你需要能够复制对象。

我如何将该数组中的值分配给临时数组?

char temporary_array[width]; // this is a C99 VLA, you might want to 
                             // allocate the array differently
memcpy(temporary_array, second_element_ptr, width);

我如何创建该临时数组?

哦,我想我错误地接受了这些问题。对于包含单个元素的小数组,您可以在VLA上冒险。或者您可以按如下方式使用malloc:

// an array half the size of the input
// using char*, since unlike void* we can do arithmetic on it
char *big_temp_array = malloc(width * (nel + 1)/2);

顺便说一句,gcc支持void*上的算术作为编译器扩展,将其视为char*上的算术。由您决定是否可以/将使用它。