【问题标题】:Swap function using void pointers [duplicate]使用 void 指针交换函数 [重复]
【发布时间】:2015-04-13 00:14:28
【问题描述】:

我想创建一个可通用用于任何数据类型的交换函数。我知道以下函数适用于整数:

void swap(void *a, void *b)
{
    int temp;
    temp = *(int*)a;
    *(int*)a = *(int*)b;
    *(int*)b = temp;
}

这适用于字符串:

void swap(void *a, void *b)
{
    void *temp;
    temp = *(void**)a;
    *(void**)a = *(void**)b;
    *(void**)b = temp;
}

【问题讨论】:

标签: c swap void-pointers


【解决方案1】:

如果您也传递指针的大小(如在qsort 中),那么您可以这样做:

void swap(void * a, void * b, size_t len)
{
    unsigned char * p = a, * q = b, tmp;
    for (size_t i = 0; i != len; ++i)
    {
        tmp = p[i];
        p[i] = q[i];
        q[i] = tmp;
    }
}

用法:

struct Qux x, y;
swap(&x, &y, sizeof(Qux));

(您可能希望将restrict 限定符添加到指针,或者以其他方式进行自我交换测试。)

【讨论】:

  • 次优,但直截了当!
  • 有些类型不能轻易复制,并且 C 缺少复制 ctor...
  • @chqrlie:有最优解的请贴出来!
  • @Kerrek SB:没有绝对最优的解决方案,它取决于架构、通过的平均长度、内联、编译器的敏锐度......对标准尺寸进行额外测试的内联函数可能会生成更快的代码一般情况下的小损失。
  • @chqrlie:只是为了早点回来,以防万一没有工作需要。
【解决方案2】:

您应该至少阅读一次C FAQ list。很高兴看到人们随着时间的推移思考了什么。

Why can't I perform arithmetic on a void * pointer? 与您的问题相关:

编译器不知道指向对象的大小。 (请记住,指针运算总是根据指向的大小;另请参见问题 4.4。)因此,不允许对 void * 进行运算(尽管某些编译器允许将其作为扩展)。在执行算术运算之前,将指针转换为char * 或您尝试操作的指针类型(另请参阅问题 4.5 和 16.7)。

同样相关的是Suppose I want to write a function that takes a generic pointer as an argument and I want to simulate passing it by reference. Can I give the formal parameter type void ** ...:

C 中没有泛型的指针到指针类型。void * 充当泛型指针只是因为当其他指针类型分配给和从void * 分配时会自动应用转换(如果需要);如果尝试间接指向指向void * 以外的指针类型的void ** 值,则无法执行这些转换。当您使用void ** 指针值时(例如,当您使用* 运算符访问void * 值时void ** 指向的值),编译器无法知道@987654335 @value 曾经是从其他一些指针类型转换而来的。它必须假定它只不过是一个void *;它不能执行任何隐式转换。

【讨论】:

    【解决方案3】:

    这是另一个答案:

    void swap(void *a, void *b, size_t width)
    {
        void *temp = malloc(width);
        memcpy(temp, b, width);
        memcpy(b, a, width);
        memcpy(a, temp, width);
        free(temp);
    
    }
    

    【讨论】:

    • @BLUEPIXY 如果width是要分配的字节数,为什么说一定要sizeof width呢?如果我们假设 size_t 是 4 个字节(例如),那么 memcpy 只会在 *a*b 之间交换 4 个字节;如果ab 指向大于sizeof width 的4 个字节的东西,那不是问题吗?不幸的是,您的评论根本没有提供任何信息,所以我希望能澄清一下。
    • @chqrlie 您能否详细说明您的评论,以便为什么会出现这种情况?例如,泄漏在哪里并不明显,特别是如果width 是首先要分配的字节数,或者为什么widthsizeof width 之间的区别在malloc 期望要分配的字节数,而不是用于指定它的变量的大小。
    • @code_dredd:很抱歉造成混淆,BLUEPIXY 和我的评论解决了 Connor 写的 malloc(sizeof width) 的原始答案代码中的一个错误,如果 width > sizeof width 是不正确的并导致未定义的行为。康纳修复了他的答案,但没有发表评论让我们知道修复并删除过时的评论。
    • @chqrlie 哦,好的,这完全有道理,b/c 我没看到。谢谢
    • @BLUEPIXY:您的评论已过时:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 2016-05-03
    • 2016-06-02
    • 2011-07-31
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    相关资源
    最近更新 更多