3

Consider the following piece of code :

int main() {    
    long long * x = new long long [10]; // array of long long
    long a = (long) x;  // address of first element
    long b = (long) (x+1); //address of second element
    long c = b - a ;  // first difference
    long d = (long) ((x+1) - x);  // second difference
    std::cout << c << std::endl ;
    std::cout << d << std::endl ;
    return 0;
}

The program out puts first 8, then 1 . I have got some understanding of pointers, and how to use them. I have come to the conclusion that adding +1 to a raw pointer value will increment it by the size of the thing it is pointing. This feature is unfamiliar to me.

So my question is why do pointer types behave like this? What would be the use of such behaviour ?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Evdzhan Mustafa
  • 3,645
  • 1
  • 24
  • 40

5 Answers5

2

Yes, pointer math works based on the size of the type it points to. The most basic example of why is array indexing let's says E1[E2] which is just syntactic sugar for *((E1)+(E2)). If it did not work this way then array indexing would not work properly.

For reference array subscripting is covered in the draft C++ standard section 5.2.1 Subscripting which says:

[...]The expression E1[E2] is identical (by definition) to *((E1)+(E2))[...]

the draft C99 standard says the same thing in section 6.5.2.1 Array subscripting.

Here is a reference that goes into all the details of pointer arithmetic.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
2

You have some problems in your understanding here which show up in the comments

int main() {

    // This one is fine
    long long * x = new long long [10]; // array of long long

    // This does not do what you think it does. It casts a pointer to a
    // long then assigns it to a. x is the address of the first element,
    // but you are putting it into a long. Did you mean:
    //     long * a = x;
    long a = (long) x;  // address of first element

    // Same mistake as above, save that b is now the address of the
    // second element, cast to a long
    long b = (long) (x+1); //address of second element

    // Now, 'c' will be the difference between the two pointers. As under
    // pointer arithmetic, x+1 will move on by one long, the pointer has
    // moved on by sizeof(long) bytes, i.e. either 4 or 8 depending on
    // your platform
    long c = b - a ;  // first difference

    // this is doing long d = long (1)
    long d = (long) ((x+1) - x);  // second difference

    std::cout << c << std::endl ;

    std::cout << d << std::endl ;

    return 0;
}
abligh
  • 24,573
  • 4
  • 47
  • 84
2

You can use it like this:

struct Some {
  /* some fields */
};

Some* vals = Some[100];
for (Some* ptr = vals; ptr != vals + 100; ++ptr) {
  cout << *ptr << endl;
}
/* or */
for_each(vals, vals + 100, [](const Some& arg) { cout << *ptr << endl; });

You don't have to worry about the size of Some structure.

Pavel Davydov
  • 3,379
  • 3
  • 28
  • 41
2

Pointer arithmetic allows you to write code that processes an array. Consider summing an array of ints:

int values[] = { 0, 1, 2, 3};
int* current = values;
int* end = values + 4;
int sum = 0;
while (current != end)
{
    sum += *current;
    ++current;
}

Of course, there are easier ways to accomplish this than using raw pointers, so don't ever write code as complicated as this to do something that is simpler to do another way. As other answers have pointed out, array indexing is translated into pointer arithmetic by the compiler: values[2] is equivalent to saying *(values + 2) so in this case looping over the array with the much simpler code is what you should do.

for (int i = 0; i < 4; ++i)
{
    sum += values[i];
}

There are more advanced reasons to use pointer arithmetic because it can actually help to simplify implementation; for example I've used it before in an assignment along with reinterpret_cast to create a free list memory allocator.

masrtis
  • 1,282
  • 17
  • 32
  • Put a `Nan` at the end of your `values` array and you can then do `while (*values) sum += *values++;`. This is likely to be faster than array indexing. – michaelmeyer Mar 08 '14 at 18:14
  • @doukremt This might work if you're keeping floating point exceptions disabled, and (more importantly) if you are using a float array instead of an int array. – masrtis Mar 08 '14 at 18:21
1

Let's say you have an array of integers and that on your platform an integer consists of 4 bytes. An int pointer can now legally point to the first, fifth, ninth etc. byte of that array, but it may not legally point to say the second or third byte of the array (because that wouldn't be the start of an int object).

So since pointer arithmetic uses the size of the given type, you can only get legal pointer by performing pointer arithmetic on the array (except if your index is out of bounds) without casting to a different pointer type. Otherwise it would be much easier to accidentally create illegal pointers through arithmetic.

It's also more convenient since, if C didn't automatically do this, the programmer would have to manually multiply by the type's size anyway in 99% of the use cases.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • Understatement. The programmer would forget to multiply 20% of the time, and get the multiplier wrong the other 90% of the time ;-) – vonbrand Mar 08 '14 at 18:13