强制转换为void指针总是安全的吗? [英] Is casting to pointers to pointers to void always safe?

查看:105
本文介绍了强制转换为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;
}

输出:

one, two

two, one

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

我使用此程序在 K& R 中模拟了交换功能,以演示功能指针的使用,我的问题是void pointer的类型转换是否始终是安全的,还是是否有任何替代方法.

I used this program to simulate the swap function in K&R, to demonstrate the use of the function pointer, and my question is whether the cast of the void pointer is always safe, or if there is any way to replace it.

推荐答案

否,传递char**并不一定安全,因为在期望void**(实际上是void*[]函数参数的地方)的地方传递了char** .编译器使您执行显式强制转换的事实对此有所提示.

No, it is not necessarily safe to pass a char** where a void** (which is what a void*[] function parameter actually is) is expected. The fact that the compiler makes you perform an explicit cast is a hint about that.

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

In practice, it is likely to be fine. Strictly speaking, however, you usually have no guarantee that sizeof (T*) == sizeof (U*) for distinct types T and U. (For example, you could imagine a hypothetical system where sizeof (int*) < sizeof (char*) because pointers-to-int are aligned and therefore don't need to store the least significant bits.) Consequently, your swap function might index into the v array using the wrong offsets.

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

Also see Q4.9 from the comp.lang.c FAQ: Can I give the formal parameter type void **, and do something like this?

要安全地呼叫swap,您应该执行以下操作:

To call swap safely, you should do something like:

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

尽管会交换temp的元素,而不是s的元素.

although that would swap the elements of temp, not of s.

如果要编写swap,通常应使此函数使用void*参数(而不是void**)和size_t参数,该参数指定每个元素的大小.然后,您的函数可以将void*强制转换为char*并交换单个字节:

If you're authoring swap, in general you should make such a function take a void* argument (instead of a void** one) and a size_t argument that specifies the size of each element. Your function then could cast the void* to char* safely and swap individual bytes:

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答案.

这篇关于强制转换为void指针总是安全的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆