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