Why a pointer + 1 add 4 actually
Short answer
The address of the pointer will be incremented by sizeof(T)
where T
is the type pointed to. So for an int
, the pointer will be incremented by sizeof(int)
.
Why?
Well first and foremost, the standard requires it. The reason this behaviour is useful (other than for compatibility with C) is because when you have a data structure which uses contiguous memory, like an array or an std::vector
, you can move to the next item in the array by simply adding one to the pointer. If you want to move to the nth item in the container, you just add n.
Being able to write firstAddress + 2
is far simpler than firstAddress + (sizeof(T) * 2)
, and helps prevent bugs arising from developers assuming sizeof(int)
is 4 (it might not be) and writing code like firstAddress + (4 * 2)
.
In fact, when you say myArray[4]
, you're saying myArray + 4
. This is the reason that arrays indices start at 0; you just add 0 to get the first element (i.e. myArray points to the first element of the array) and n to get the nth.
What if I want to move one byte at a time?
sizeof(char)
is guaranteed to be one byte in size, so you can use a char*
if you really want to move one byte at a time.
Because pointers are designed to be compatible with arrays:
*(pointer + offset)
is equivalent to
pointer[offset]
So pointer aritmetic doesn't work in terms of bytes, but in terms of sizeof(pointer base type)
-bytes sized blocks.
Pointer arithmetic is a tricky subject. A pointer addition means passing to some next pointed element. So the address is incremented by the sizeof
the pointed element.
Consider what a pointer is... it's a memory address. Every byte in memory has an address. So, if you have an int
that's 4 bytes and its address is 1000, 1001 is actually the 2nd byte of that int
and 1002 is the third byte and 1003 is the fourth. Since the size of an int
might vary from compiler to compiler, it is imperative that when you increment your pointer you don't get the address of some middle point in the int
. So, the job of figuring out how many bytes to skip, based on your data type, is handled for you and you can just use whatever value you get and not worry about it.
As Basile Starynkvitch points out, this amount will vary depending on the sizeof
property of the data member pointed to. It's very easy to forget that even though addresses are sequential, the pointers of your objects need to take into account the actual memory space required to house those objects.