36
#include<stdio.h>
int main(void){
  int *ptr,a,b;
  a = ptr;
  b = ptr + 1;
  printf("the vale of a,b is %x and %x respectively",a,b);

  int c,d;
  c = 0xff;
  d = c + 1;
  printf("the value of c d are %x and %x respectively",c,d);
  return 0;
}

the out put value is

the vale of a,b is 57550c90 and 57550c94 respectively
the value of c d are ff and 100 respectively%  

it turns out the ptr + 1 actually, why it behave this way?

mko
  • 21,334
  • 49
  • 130
  • 191
  • 1
    See [my previous answer](http://stackoverflow.com/a/8772201/119527) to a question like this. – Jonathon Reinhart Jul 22 '12 at 07:14
  • You should use `%p` in `printf` format strings for pointers. Don't use `%x` for that, it is not portable (because pointers and `int`-s may have different bit width). – Basile Starynkevitch Jul 22 '12 at 08:12
  • You really should enable all warnings for your compiler, e.g. `-Wall` if compiling with `gcc`; your code has several mistakes! In particular `ptr` remains uninitialized but is used (undefined behavior). – Basile Starynkevitch Jul 22 '12 at 08:20
  • @BasileStarynkevitch Yes you are right. I just check the `%x`and '%p' , there's difference.And for clang compiler, does it also can be use `-Wall` to enable warning? – mko Jul 22 '12 at 08:28

6 Answers6

52

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.

  • for 64 bit machines, it may be as big as 8 bytes. – Aftnix Jul 22 '12 at 07:10
  • @Aftnix yes, but what's the problem with that? –  Jul 22 '12 at 07:11
  • a pointer will be big enough to hold a memory address of the platform. If you need 8 bytes to hold memory address, it will be 8bytes regardless of what its pointing to. I'm just saying that you should point this out in your answer for the sake of generality. there is nothing wrong with your answer, but pointer arithmetic makes sense if you have "fixed" sized pointer variable. I'm just saying before stating the principle of pointer arithmetic, you should say that every platform has a native fixed pointer size. Thats why pointer arithmetic is consistent in different platform. – Aftnix Jul 22 '12 at 07:20
  • +1 for letting me know the connection between array and pointer. but I can't make your code work: printf("%p",ptr[1]) – mko Jul 22 '12 at 08:22
  • euh not, printf("%p", ptr + 1). Note that `*(ptr + offset)` is equivalent to `ptr[offset]`, but `ptr + offset` itself is ***not***! –  Jul 22 '12 at 10:04
  • @Aftnix I'm not saying that sizeof(void *) is different, I'm saying that the difference between two pointers is dependent of the type it points to. –  Jul 22 '12 at 10:06
  • @Baba Thanks! Only if 4 more people upvoted this... I can haz that populist badge, please? :D –  Oct 14 '12 at 17:52
42

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.

Yevgeny Simkin
  • 27,946
  • 39
  • 137
  • 236
11

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.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
5

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.

OMGtechy
  • 7,935
  • 8
  • 48
  • 83
2

A pointer is used to point to a specific byte of memory marking where an object has been allocated (technically it can point anywhere, but that's how it's used). When you do pointer arithmetic, it operates based on the size of the objects pointed to. In your case, it's a pointer to integers, which have a size of 4 bytes each.

Jimmy
  • 27,142
  • 5
  • 87
  • 100
1

Let consider a pointer p. The expression p+n is like (unsigned char *)p + n * sizeof *p (because sizeof(unsigned char) == 1). Try this :

#include <stdio.h>
#define N   3

int
main(void)
{
    int i;
    int *p = &i;
    printf("%p\n", (void *)p);
    printf("%p\n", (void *)(p + N));
    printf("%p\n", (void *)((unsigned char *)p + N * sizeof *p));
    return 0;
}
md5
  • 23,373
  • 3
  • 44
  • 93