【问题标题】:Swap function that works for any types in C适用于 C 中任何类型的交换函数
【发布时间】:2021-04-05 05:26:28
【问题描述】:

我不知道这是否可能,但我正在尝试做一个 swap 函数,它交换两个变量并适用于任何类型的变量,只要要交换的两个变量是相同的类型,我确实是使用void * 类型:

#include <limits.h>
#include <stdio.h>

void ft_swap(void **a, void **b)
{
    void    *tmp;

    tmp = *a;
    *a = *b;
    *b = tmp;
}

int main(void)
{
    int a = 5;
    int b = INT_MAX;
    unsigned long c = 10;
    unsigned long d = ULONG_MAX;

    printf("BEFORE\na = %d\nb = %d\nc = %zu\nd = %zu\n", a, b, c, d);
    ft_swap((void **)&a, (void **)&b);
    ft_swap((void **)&c, (void **)&d);
    printf("AFTER\na = %d\nb = %d\nc = %zu\nd = %zu\n", a, b, c, d);
    return (0);
}

输出是:

BEFORE
a = 5
b = 2147483647
c = 10
d = 18446744073709551615
AFTER
a = 0
b = 5
c = 18446744073709551615
d = 10

我知道 void * 类型的大小与 unsigned long 相同,但是有人可以解释一下我的 int 变量有什么问题吗,对我来说它应该可以工作,因为 int 是一个较小的类型? 5 被交换了,但是 INT_MAX 变成了 0,这里发生了什么?

编辑:我做了一个你告诉我的版本:使用 long long 指针,但它也不起作用,它改变了 int 的值。

【问题讨论】:

  • 如果void * 在您的系统上大于int,例如大多数 64 位系统是 8 字节而不是 4 字节,您只需覆盖 ab 之后发生在内存中的任何内容的 4 字节。如果它们相邻,则其中一个可能会覆盖另一个。
  • 我会使用unsigned long long * 而不是void *。但是没关系,hwat,只要您不传递 sizeinfo,此函数将主要调用未定义的行为。
  • 实际上,sizeof(void *) 不必与sizeof(unsigned long) 相同。尝试使用 MSVC 编译器在 64 位 Windows 系统上执行此操作,它会崩溃。实际上,正如您所指出的,在实际类型与 sizeof(void *) 不同的任何情况下,它都会崩溃。
  • 如果你想要一个通用的 integer 类型,它可以适应各种整数 指针,使用例如uintptr_t 代替。但为了“正确”解决您的问题,我建议您改为对generic selection 进行一些研究。
  • (void **) 强制转换用于迫使编译器接受您的代码,这强烈表明存在问题。

标签: c


【解决方案1】:

你的交换函数完全没有意义(我什至无法猜测它背后的想法是什么)。

您的函数必须知道对对象的引用及其大小。然后需要复制它们占用的内存。

这里你有一个更正确的:

void swap(void *d1, void *d2, size_t size)
{
    unsigned char temp[size];

    memcpy(temp, d1, size);
    memcpy(d1, d2, size);
    memcpy(d2, temp, size);
}

struct st
{
    int a;
    double b;
    char c[10];
};

int main(void)
{
    int a = 5;
    int b = INT_MAX;
    unsigned long c = 10;
    unsigned long d = ULONG_MAX;
    struct st x = {1,2.0, "text1"};
    struct st y = {5,20.0, "text2"};


    printf("BEFORE\na = %d\nb = %d\nc = %zu\nd = %zu\n", a, b, c, d);
    swap(&a, &b, sizeof(a));
    swap(&c, &d, sizeof(c));
    printf("AFTER\na = %d\nb = %d\nc = %zu\nd = %zu\n", a, b, c, d);
    printf("struct before: %d %f %s, %d %f %s\n", x.a, x.b, x.c, y.a, y.b, y.c);
    swap(&x, &y, sizeof(x));
    printf("struct after: %d %f %s, %d %f %s\n", x.a, x.b, x.c, y.a, y.b, y.c);
    return (0);
}

https://godbolt.org/z/er95YYjca

【讨论】:

    猜你喜欢
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 1970-01-01
    相关资源
    最近更新 更多