1

For example.

int a[]={3,4};
int *p1=a;
int *p2=a+1;

In the last line, how can the compiler tell that the +1 in this line is not just a common adding, but a address adding. How can it distinguish from the common adding such as int i=1+2.

Can someone explain it at the register level?

henryyao
  • 1,758
  • 6
  • 23
  • 37
  • 2
    Um, by the fact that it's *not* operating on an int? – Ignacio Vazquez-Abrams Jul 21 '13 at 04:43
  • 2
    adding one to a pointer make it to point to next element of its kind in continues memory location. e.g. on adding 1 to `int*` pointer make to to point next int. Now understand even a int is 4 (or 8) bytes pointer value is first cell address value (but this pointer represents complete `int`). Now on adding `1` to this pointer value it will start pointing to next `int` in sequence so magnitude-wise pointer address value incremented by size of `int`. So adding `1` to a pointer is not arithmetically but logical increments it. – Grijesh Chauhan Jul 21 '13 at 05:25

2 Answers2

3

When you add a scalar to a pointer it is like doing &pointer[scalar]. For example:

int * path = 0x1234;
path += 1;
printf("%p\n", path);

The above code prints out 0x1238 on a 32-bit system.

EDIT: to clarify, adding n to a pointer offsets the pointer by n * sizeof(element) bytes.

Alex Nichol
  • 7,512
  • 4
  • 32
  • 30
  • What I learned is when using pointer[scalar], the compiler will treat it as *(pointer+scalar), not the other way. – henryyao Jul 21 '13 at 04:50
  • @henryyao That is a distinction without a difference. Both are treated the same. It doesn't matter which came first. – user207421 Jul 21 '13 at 05:32
1

It distinguishes based on the type of the object being added. If it's a pointer, then the address is increased by the number you specify multiplied by the size of the object the pointer is specified to point at.

IOW, given some type T, and an addition like:

T *result = base + increment;

...it's basically equivalent to something like this:

char *raw_address = (char *)base_address;

raw_address += increment * sizeof(T);

result = (T *)raw_address;

Note, however, that in quite a few cases the CPU may be able to handle the scaling for at least some types (e.g., 1, 2, 4, or 8-byte types) in a single instruction (e.g., Intel x86/x64 and compabibles can combine scaling and addition like this).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • So the compiler is smart enough to distinguish int i=1+3 from int *p=0x1234+1, right? – henryyao Jul 21 '13 at 04:52
  • 3
    Yes and no. As you've shown it (`0x1234+1`) it's just doing math on a couple of integers, so that won't be scaled. If one of the inputs is actually a pointer, however, it then distinguishes math on it from math on integers (e.g., `int *p = (int *)0x1234; p += 4;`). – Jerry Coffin Jul 21 '13 at 04:57