You are currently browsing the Sticky Bits blog archives for April, 2011.

GNU, and void pointers

April 18th, 2011

Void pointers were introduced in ANSI C as ‘generic’ pointers; or, if you prefer, ‘pointers to no particular type’. They were designed to replace unsigned char* pointers in instances where the type of the object being pointed to could change.

unsigned char* has the least restrictive alignment – it aligns on a byte boundary. This means an unsigned char* pointer could be used to point to any object (with an appropriate cast, of course).

Remember, though, the type of a pointer defines how to interpret the memory at the address held in the pointer. Using an unsigned char* to point to any object is a bit of an abuse of such a pointer (unless, of course, the thing you’re referencing actually IS an unsigned char!)

Hence, the introduction of the void* – a pointer that imposes no requirements on the memory it references.

The void pointer has the same alignment as an unsigned char*; that is, void pointers align on byte boundaries.

Because void pointers are generic (and are effectively useless on their own) you can implicitly convert any pointer to and from a void*.

There is one little wrinkle with void pointers: you cannot perform (pointer) arithmetic on them. The following code fails to compile:

int main (void)
{
  int i;
  void *p = &i;
  p++;  /* But what’s the sizeof(void)?! */ 
}

When you increment (or perform any other arithmetic) on a pointer it modifies the value of the pointer by the size of the type it references.

In the case of a void pointer it doesn’t point to any type, so the compiler cannot know how to manipulate the pointer value.

Except, it seems, in the GNU compiler.

The above code will compile with no errors or warnings. GNU have included an extension that treats void* just like unsigned char*. So with a GNU compiler the value of p would increase by one. We can only assume that, since a void* has the same alignment as an unsigned char*, GNU thought its arithmetic should work the same way, too.

This code is highly unportable (and not even standards compliant). If you’re using little tricks like this in your everyday code be prepared for a painful life when you port to another compiler.

%d bloggers like this: