3
#include <stdio.h>

void swap(void *v[], int i, int j)
{
    void *tmp;

    tmp = v[i];
    v[i] = v[j];
    v[j] = tmp;
}

int main(void)
{
    char *s[] = {"one", "two"};
    printf("%s, %s\n", s[0], s[1]);
    swap(s, 0, 1);
    printf("%s, %s\n", s[0], s[1]);
    return 0;
}

输出

one, two

two, one

警告: no compatible pointer casting, need void**, but char

我用这个程序模拟了K&R中的交换函数,演示了函数指针的使用,我的问题是 的转换是否void pointer总是安全的,或者是否有任何方法可以替换它。

4

3 回答 3

8

char**不,传递a不一定安全void**(这是void*[]函数参数的实际值)是预期的。编译器让您执行显式转换这一事实暗示了这一点。

在实践中,它可能会很好。但是,严格来说,您通常无法保证sizeof (T*) == sizeof (U*)对于不同的类型TU. (例如,您可以想象一个假设的系统,sizeof (int*) < sizeof (char*)因为指向的指针int是对齐的,因此不需要存储最低有效位。)因此,您的函数可能会使用错误的偏移量swap索引到数组中。v

另请参阅 comp.lang.c 常见问题解答中的 Q4.9:我可以给出形式参数类型void **,并执行类似的操作吗?

为了swap安全调用,您应该执行以下操作:

void* temp[] = { &s[0], &s[1] };
swap(temp, 0, 1);

虽然这会交换 的元素temp,而不是的元素s

如果你正在创作swap,通常你应该让这样的函数接受一个void*参数(而不是void**一个)和一个size_t指定每个元素大小的参数。然后,您的函数可以安全地void*转换为char*并交换单个字节:

void swap(void* p, size_t elementSize, size_t i, size_t j)
{
    char* item1 = p;
    char* item2 = p;

    item1 += i * elementSize;
    item2 += j * elementSize;

    while (elementSize-- > 0) {
        char temp = *item1;
        *item1 = *item2;
        *item2 = temp;
        item1++;
        item2++;
    }
}

编辑:另请参阅此 StackOverflow 对类似问题的回答

于 2013-05-15T05:11:31.303 回答
-1

您需要在交换调用中对指针进行类型转换。将其更改为swap ( ( void * )s, 0, 1 );

于 2013-05-15T03:47:07.173 回答
-1

为了避免警告调用函数如下,

swap((void *) s, 0, 1);

将任何指针转换为 void 指针总是安全的。

于 2013-05-15T03:48:06.423 回答