36

I'm a bit confused with a void* pointer in C. Especially after reading this question: Is the sizeof(some pointer) always equal to four?, where one person says there is no guarantee that sizeof(int *) == sizeof(double *)

My question is: is there a guarantee of sizeof(void*) >= sizeof(any other pointer type)? In other words, can I always assign a some_type* pointer to a void* pointer and then get it back as some_type*?

Community
  • 1
  • 1
facha
  • 11,862
  • 14
  • 59
  • 82

2 Answers2

34

Only data pointers. void * can hold any data pointer, but not function pointers.

Here is a C FAQ.

void *'s are only guaranteed to hold object (i.e. data) pointers; it is not portable to convert a function pointer to type void *. (On some machines, function addresses can be very large, bigger than any data pointers.)

As for the first part, yes, different types can have pointers of different sizes:

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • 7
    However, different-sized pointers is rare to nonexistent in modern systems. – Greg Hewgill Aug 02 '11 at 08:02
  • And note "can hold", not "is at least as big". There's nothing in the standard that says that for example, `double*` pointers can't be wastefully big and just not use some of their bits. You could have `sizeof(double*) > sizeof(void*)` even though a `void*` can hold every value of `double*`. – Steve Jessop Aug 02 '11 at 08:57
  • 1
    no arguments convinced me yet (of course std is the bible, but it can be badly designed): there must exist a "register" able to hold the ''biggest'' "pointer"; and I expect "void *" to be an "union" of all the possible pointers, so that it can mean for real "pointer to anything". Before I can use it, I need to cast it, and then it must acquire a "specific form". But sizeof(void *) should give the size of the "biggest" one, able to keep function pointers too (whatever they are) – ShinTakezou Aug 02 '11 at 09:41
  • @ShinTakezou: A counterexample would be a system in which pointers are not very compact, e.g. classic x86: You need a 16+16 bits pointer when you're dereferencing them, but they contain only 20 bits of information. Since you never dereference `void*`, that doesn't need to be 32 bits but could be 24 bits. – MSalters Aug 02 '11 at 10:29
  • 1
    In this context it’s notable that POSIX blatantly violates this point from the C standard, by requiring that `void*` *can* in fact hold a method pointer. – Konrad Rudolph Aug 02 '11 at 12:43
  • @Konrad: "blatantly violates" in the sense that not every conforming C implementation is a conforming Posix implementation. Which is hardly surprising given that (just for starters) Posix introduces new library headers. – Steve Jessop Aug 03 '11 at 10:25
  • @Steve “blatantly violates” in the sense that they chose to require UB in a case (`dlsym`) where they could have got away with well-defined C code. And in fact, this decision may be revisited in the future, according to the man page. – Konrad Rudolph Aug 03 '11 at 11:12
17

The value stored in the pointer is an address to memory. If you're on a 32-bit system, that pointer into memory is going to be 32 bits (or four bytes) long. If you're on a 64-bit system, that pointer into memory is going to be 64 bits (or eight bytes) long.

The size of the data that holds the location in memory has nothing to do with the size of the data represented at that location in memory.

As for how a char * differs from a double *, the char * can point to any location, but the double * has to point to something along an eight-byte boundary. Larger data has to be aligned according to the rules of the processor you're on. So, pointers to small data are not generally compatible with pointers to large data (e.g. you shouldn't point a double * pointer to a char * address); but you're save going in the other direction (e.g. you can point a char * pointer to a double * address).

unpythonic
  • 4,020
  • 19
  • 20
  • 4
    This is a good practical answer but it looks like the OP is looking for a standards-pedantic answer. – Chris Lutz Aug 02 '11 at 07:45
  • As Chris said. What you express here is what practice tells us, but as far as the language standard is concerned, all bets are off. ;-) – DevSolar Aug 02 '11 at 07:49
  • The language rules are what they are to **allow** implementations on systems where addressing isn't regular. The language designers did this on purpose. – Bo Persson Aug 02 '11 at 09:01
  • +1 . But alignment is not a need on all possible machines; though, it is very common (i.e. it is so); e.g. if I remember well, 68020 can access odd addresses while reading word (16)or long word (32) data, though the access is slower (and so, aligning data will make your program run faster) – ShinTakezou Aug 02 '11 at 09:45
  • I need example of systems where addressing "isn't regular" **and** the language can't hide it (the only reason I can accept standard writers wrote that in that way, is that hiding and allowing the "intuitive" fact that a pointer is a pointer no matter to what, would have been impossible ...) – ShinTakezou Aug 02 '11 at 09:48
  • The most common case is when the 'natural' pointer size is a word pointer, and byte pointers need to represent an additional offset within that word. As for why it doesn't hide it, it's not that it "can't", it's because C isn't in the business of hiding stuff like that. – Random832 Aug 02 '11 at 12:34