Howard Chu wrote: > extern void getit( void **arg ); > > main() { > union { > int *foo; > void *bar; > } u; > > getit( &u.bar ); > printf("foo: %x\n", *u.foo); > }
Rask Ingemann Lambertsen wrote: > As far as I know, memcpy() is the answer: You don't need a union or memcpy() to convert the pointer types. You can solve the "void **" aliasing problem with just a cast: void *p; getit(&p); printf("%d\n", *(int *)p); This assumes that getit() actually writes to an "int" object and returns a "void *" pointer to that object. If it doesn't then you have another aliasing problem to worry about. If it writes to the object using some other known type, then you need two casts to make it safe: void *p; getit(&p); printf("%d\n", (int)*(long *)p); If writes to the object using an unknown type then you might able to use memcpy() to get around the aliasing problem, but this assumes you know that two types are compatable at the bit level: void *p; int n; getit(&p); memcpy(&n, p, sizeof n); printf("%d\n", n); The best solution would be to fix the interface so that it returns the pointer types it acutally uses. This would make it typesafe and you wouldn't need to use any casts. If you can't fix the interface itself the next best thing would be to create your own wrappers which put all the nasty casts in one place: int sasl_getprop_str(sasl_conn_t *conn, int prop, char const **pvalue) { assert(prop == SASL_AUTHUSER || prop == SASL_APPNAME || ...); void *tmp; int r = sasl_getprop(conn, prop, &tmp); if (r == SASL_OK) *pvalue = (char const *) tmp; return r; } Unfortuantely, there are aliasing problems in the Cyrus SASL source that can still come around and bite you once LTO arrives no matter what you do in your own code. You might want to see if you can't get them to change undefined code like this: *(unsigned **)pvalue = &conn->oparams.maxoutbuf; into code like this: *pvalue = (void *) &conn->oparams.maxoutbuf; Ross Ridge