#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;
}
Output:
one, two
two, one
Warning: no compatible pointer casting, need void**, but char
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.
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.
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.
Also see Q4.9 from the comp.lang.c FAQ: Can I give the formal parameter type void **
, and do something like this?
To call swap
safely, you should do something like:
void* temp[] = { &s[0], &s[1] };
swap(temp, 0, 1);
although that would swap the elements of temp
, not of s
.
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++;
}
}
Edit: Also see this StackOverflow answer to a similar question.
You need to typecast the pointer in swap call. Change it to swap ( ( void * )s, 0, 1 );
To avoid the warning call the function as follows,
swap((void *) s, 0, 1);
It is always safe to cast any pointer as a void pointer.
来源:https://stackoverflow.com/questions/16556443/is-casting-to-pointers-to-pointers-to-void-always-safe