是否指向void的指针总是安全的?

pup*_*007 3 c pointers void

#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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

one, two

two, one
Run Code Online (Sandbox Code Playgroud)

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

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

jam*_*lin 7

不,传递一个(实际上是一个函数参数)预期的char**地方并不一定安全.编译器使您执行显式转换的事实是一个提示.void**void*[]

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

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

swap安全地打电话,你应该做的事情如下:

void* temp[] = { &s[0], &s[1] };
swap(temp, 0, 1);
Run Code Online (Sandbox Code Playgroud)

虽然这会交换元素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++;
    }
}
Run Code Online (Sandbox Code Playgroud)

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