交换void *数组无法正常工作

时间:2017-03-08 09:23:11

标签: c arrays void-pointers

我有一个复数的数组,我只想在两个元素之间交换。但是,我想实现未知类型的交换(使用void *)。所以我使用我看到here的第一个交换实现编写了以下代码:

#include<stdio.h>

typedef struct complex complex;

struct complex {
    int real;
    int img;
};

void swap(void *arr[], int i, int j)
{
    void *temp;
    temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

void printComplexArray(complex* cArr, size_t len)
{
    int i;
    for (i = 0; i < len; i++)
    {
        printf("Cell %d : real- %d , img- %d\n", i, cArr[i].real, cArr[i].img);
    }
}

void main(void)
{
    complex cArr[] = { { 22, 3 },{ 1, 13 },{ 5, 7 },{ 8, 4 } };
    size_t cLen = (sizeof(cArr) / sizeof(cArr[0]));
    swap(cArr, 1, 2);
    printComplexArray(cArr, cLen);
}

我希望得到:

Cell 0 : real- 22 , img- 3
Cell 1 : real- 5 , img- 7
Cell 2 : real- 1 , img- 13
Cell 3 : real- 8 , img- 4

但我得到了:

Cell 0 : real- 22 , img- 1
Cell 1 : real- 3 , img- 13
Cell 2 : real- 5 , img- 7
Cell 3 : real- 8 , img- 4                     

正如您所看到的,不仅交换没有正确执行 - 某些数组元素的内容也发生了变化。你能解释一下原因,我该如何解决这个问题?

3 个答案:

答案 0 :(得分:5)

你可能想要这个:

void swap(struct complex arr[], int i, int j)
{
    struct complex temp;
    temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

您的解决方案交换指针,但您的数组不包含指针,而是struct complex s。这基本上是编译器警告告诉你的。

如果你真的想要交换未知类型,你需要这个:

void swap(void *arr, int i, int j, size_t size)
{
    char temp[size];
    char *a = (char*)arr;

    memcpy(temp, (a + size * i), size);
    memcpy((a + size * i), (a + size * j), size);
    memcpy((a + size * j), temp, size);
}
...
swap(cArr, 1, 2, sizeof(*cArr));

size参数是必需的,因为如果类型未知,则类型的大小当然也是未知的,因此您需要指定大小。

对于memcpy,您需要添加<memory.h>,因此您必须自己编写memcpy,因为您只能包含<stdio.h>

有些编译器不允许使用char temp[size];,因此您可以使用char temp[MAX_SIZE]; MAX_SIZE定义未知类型的最大预期大小。

答案 1 :(得分:1)

您无法实现未知类型的交换,您需要知道类型的大小。你的函数交换指针(指针已知大小),但是你正在为它提供complex数组,而不是指针数组。试试这个(未经测试):

void swap(void *array, size_t i, size_t j, size_t element_length) {

    char *src, *dst, tmp;

    src = (char*)array + i * element_length;
    dst = (char*)array + j * element_length;

    while (element_length--) {

        tmp = *src;
        *src = *dst;
        *dst = tmp;

        src++;
        dst++;
    }
}

...

swap(cArr, 1, 2, sizeof(complex));

答案 2 :(得分:1)

使用void *(据我所知)这样做的唯一方法是重新设计结构的swap函数交换/应对字节,例如

#include<stdio.h>

typedef struct complex complex;

struct complex {
    int real;
    int img;
};


void swap(void * to, void * from, size_t len)
{
    unsigned char *uc_to   = to;
    unsigned char *uc_from = from;
    unsigned char tmp;

    for (size_t i = 0; i < len; i++)
    {
        tmp = uc_to[i];
        uc_to[i] = uc_from[i];
        uc_from[i] = tmp;
    }
}

void printComplexArray(complex* cArr, size_t len)
{
    size_t i;
    for (i = 0; i < len; i++)
    {
        printf("Cell %zu : real- %02d , img- %02d\n", i, cArr[i].real, cArr[i].img);
    }
}

int main(void)
{
    complex cArr[] = { { 22, 3 }, { 1, 13 }, { 5, 7 }, { 8, 4 } };

    size_t cLen = (sizeof(cArr) / sizeof(cArr[0]));

    swap((void *)(&cArr[0]), (void *)(&cArr[1]), sizeof(complex));

    printComplexArray(cArr, cLen);
}