In C any data pointer can be passed to a function that expects a void *
and a void *
can be stored to any pointer type. There is an implicit conversion between void *
and other pointer types. But this does not mean that this conversion is harmless. On some architectures where void *
and int *
have a different representation, converting from int *
to void *
and then back to int *
is specified as producing the same pointer value, but the converse does not hold: converting a void *
to int *
and back to void *
may produce a different value, especially if the void *
was not obtained by converting an int *
.
Interchangeability means that this implicit conversion does not change the representation of the pointer. the conversion can be operated both ways successfully: converting a character pointer to void *
and back produces the same pointer and vice versa.
Here is an example:
#include <assert.h>
#include <stdio.h>
#include <string.h>
int main() {
char *s = "abc";
char *s1;
void *p;
void *p1;
assert(sizeof(p) == sizeof(s));
memcpy(&p, &s, sizeof(p));
p1 = s;
assert(p == p1);
memcpy(&s1, &p1, sizeof(s1));
assert(s == s1);
return 0;
}
Note however that this does not imply that !memcmp(&p1, &s, sizeof(p1))
because pointers could have padding bits. Neither can you violate the strict aliasing rule by casting through a void *
:
float f = 1.0; unsigned int i = *(int *)(void *)&f'
incorrect.
float f = 1.0; unsigned int i; memcpy(&i, &f, sizeof(i));
correct if sizeof(int) == sizeof(float)
but may produce a trap value.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…