最近,我很好奇
qsort()
如何在不传递特定类型的情况下进行排序,因此我试图在不知道/关心它的类型的情况下反转数组。
有人告诉我,如果将
void *
转换为 char *
,就可以进行指针运算。
void swap(void *a, void *b)
{
char tmp = *(char *)a;
*(char *)a = *(char *)b;
*(char *)b = tmp;
}
功能
swap()
适用于类型int
&char
但不适用于float
或double
.
我不知道为什么会这样,但我看到了与
memcpy()
交换的实现,因此,我实现了:
void __swap(void *a, void *b, size_t size)
{
char buf[size];
memcpy(buf, a, size);
memcpy(a, b, size);
memcpy(b, buf, size);
}
使用
swap()
的反向函数实现:
void arr_reverse(void *arr, size_t size, size_t len)
{
for (size_t i = 0, j = len - 1; i < len / 2; i++, j--)
swap(arr + (i * size), arr + (j * size));
}
使用
__swap()
的反向函数实现:
void arr_reverse(void *arr, size_t size, size_t len)
{
for (size_t i = 0, j = len - 1; i < len / 2; i++, j--)
__swap(arr + (i * size), arr + (j * size), size);
}
__swap()
效果很好,但我不知道为什么会这样,所以问题是,swap()
和__swap()
有什么区别?
我假设这与字体大小有关
swap
的实现交换一个字节。注意
__swap
如何有第三个参数,size
。
当你交换两个项目时,你需要知道三个条信息:
所以,泛型函数可能不知道确切的类型,但它仍然需要知道该类型的大小(以字节为单位)。
void *
算术是未定义的行为。它是 GCC 扩展,C 标准不允许。
__swap
和swap
正在做完全不同的事情。第一个是交换 chunks
len 的整个 size
内存。后者只交换第一个字符,其余字符保持不变,用于更长的类型(如双精度或浮点数)
void swap(void *a, void *b)
{
char tmp = *(char *)a;
*(char *)a = *(char *)b;
*(char *)b = tmp;
}
void __swap(void *a, void *b, size_t size)
{
char buf[size];
memcpy(buf, a, size);
memcpy(a, b, size);
memcpy(b, buf, size);
}
void invalid_arr_reverse(void *vp, size_t size, size_t len)
{
unsigned char *arr = vp;
for (size_t i = 0, j = len - 1; i < len / 2; i++, j--)
swap(arr + (i * size), arr + (j * size));
}
void arr_reverse(void *vp, size_t size, size_t len)
{
unsigned char *arr = vp;
for (size_t i = 0, j = len - 1; i < len / 2; i++, j--)
__swap(arr + (i * size), arr + (j * size), size);
}
void printarr(uint32_t *arr, size_t size )
{
while(size--) printf("0x%08x\n" ,(unsigned)*arr++);
}
int main(void)
{
uint32_t arr[4] = {0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff};
uint32_t arr1[4] = {0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff};
invalid_arr_reverse(arr, 4, 4);
printarr(arr, 4);
arr_reverse(arr1, 4, 4);
printarr(arr1, 4);
}
https://godbolt.org/z/z1sYrPj6G
字节交换函数必须以不同的方式编写:
void arr_reverse(void *vp, size_t size, size_t len)
{
unsigned char *arr = vp;
for (size_t i = 0; i < len / 2; i++)
for(size_t j = 0; j < size; j++)
swap(arr + (i * size) + j, arr + (len - i -1) * size + j);
}