sah@mips.COM (Steve Hanson) (08/07/90)
Using void* in function declarations I would think will be, if not already, a very common abstraction mechanism; however it seems to have an awkwardness about it. Here's a straight forward implementation of memchr, assuming char's are unsigned: void *memchr(const void *s, int c, unsigned int n) { register unsigned char C = c; while (--n >= 0) if (*s++ == C) { return --s; } return (0); } This fails of course because of the dereference and the increment applied to void*. The dereference problem is easy to remove: void *memchr(const void *s, int c, unsigned int n) { register unsigned char C = c; while (--n >= 0) if (*(unsigned char *)s++ == C) { return --s; } return (0); } however the inc/dec cause a temporary variable to be introduced: void *memchr(const void *s, int c, unsigned int n) { register unsigned char* S = s; register unsigned char C = (unsigned char) c; while (--n >= 0) if (*S++ == C ){ return (void* )--S; } return (0); } An alternative would have been to allow void* to be completed (or inherit its type) by casts. The temporary S wouldn't be necessary that causes a bit of coding awkwardness and inefficiency due to extra store that doesn't lend itself to copy propagation removal. The code then becomes: void *memchr(const void *s, int c, unsigned int n) { register unsigned char C = c; while (--n >= 0) if (*(unsigned char*)s++ == C ){ return (void *) --(unsigned char *)s; } return (0); } Reasonable defaults would be that the size of what void* points is the same as the size of char since void* pointers have the same representation and alignment requirements as a pointer to a character type. Since this is all not true today I would expect to see the idiom: type func(void* p) { type T = p; ... ref T ... } for the most trivial of functions that march through data structures via void*. -- UUCP: {ames,decwrl,prls,pyramid}!mips!sah USPS: MIPS Computer Systems, 930 Arques Ave, Sunnyvale CA, 94086