What is the difference between these two lines of code?
int *ptr = &x;
and
void* q = &x;
int* p = q;
I'm very new to C and the concept of pointers - having been taught primarily in Java - so just a little confused.
Thanks in advance.
void *
is used to note a generic pointer in C.
Meaning it can point to any type.
So in the first case int *ptr = &x;
you use a pointer to an int
so anyone using it knows it is manipulating an integer.
In the second case void* q = &x;
you point to an integer address via a gereric pointer.
The problem is that it is not clear what type this pointer is refering to.
So the first and 2 examples have the same effect (in your specific example) but the void *
is not safe to be used like this.
void* q = &x;
It's probably worth understanding how things are represented in memory so you understand the meaning of void*
. A pointer is a position in memory containing another position in memory. For a real-world example, consider the following code:
int x = 4;
int* y = &x;
void* z = &x;
On my 64-bit system, I can use gdb to examine the memory. The results are as you see in the following table:
Address | Memory Value | C expression
================================================================================
0x7fffffffdf8c | 0x04 0x00 0x00 0x00 | int x = 4;
0x7fffffffdf98 | 0x8c 0xdf 0xff 0xff 0xff 0x7f 0x00 0x00 | int* y = &x;
0x7fffffffdf90 | 0x8c 0xdf 0xff 0xff 0xff 0x7f 0x00 0x00 | void* z = &x;
What do we see here? Well, 0x7fffffffdf8c
to 0x7fffffffdf90
is taken up by the value 0x04
and all zeros - integers on my platform are 4-bytes wide and the order is little endian, so the bytes are the opposite of what a human would expect to read. Then, we see the next 8-bytes are taken up by none other than the address of x, and likewise again for the second pointer.
So the process of using a pointer is to read the address at an address and work with that. It sounds like you might be fairly happy with that concept as is, so, moving on:
The type of the pointer does not affect the size of the pointer. This is key. Looking at both your pointer values above, they are actually both the same size. The size value here talks about the target memory - it instructs the compiler to load and operate on a certain amount (number of bytes - the size/width of a type) of memory.
void*
, as others have said, is "typeless". Rather, it is just a pointer and the compiler/C language will not be able to support you dereferencing it, since there is no type information - there is no way to safely tell how much memory at the target address you want to read.
However, this fact is sometimes useful. The idea of using types is to provide consistency in your code - if a function expects a 64-bit integer, using types enforces this requirement so that you don't introduce errors. Sometimes, however, you don't mind what type you get. In these cases, your requirements are "some memory. any memory!" - the best example of this I can think of is memcpy - which might work a little like this:
void *memcpy(void * s1, const void* s2, size_t n)
{
char *r1 = s1;
const char *r2 = s2;
while (n) {
*r1++ = *r2++;
-n;
}
return s1;
}
Adapted from uclibc. Here, the variable types do not matter at all - internally, the function decides to manipulate memory in sizeof(char)
types (char
is usually but not always a byte wide) but it could equally have operated on uint64_t
or some other value. All the type does here is control how many bytes are being considered from the start address as part of the type.
To give you another table, here's a comparison of some type sizes:
Address of ptr | Type in code | Memory it "sees" when dereferenced
===========================================================================
0x7fffffffdf90 | unsigned 64-bit | 0x8c 0xdf 0xff 0xff 0xff 0x7f 0x00 0x00
0x7fffffffdf90 | unsigned 32-bit | 0x8c 0xdf 0xff 0xff
0x7fffffffdf90 | unsigned 16-bit | 0x8c 0xdf
0x7fffffffdf90 | unsigned 8-bit | 0x8c
0x7fffffffdf90 | void* | Doesn't know how wide it is.
You might wonder why there are no casts in that libc function - well, there is no need. All pointers are the same size so nothing else needs to be done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With