0

Lets say we create an array like:

int a[4]={1,2,3,4};

Now a is the name of this array and also the pointer points to the first element a[0]. So when I want to call the elements in the array, I can use a[ i ] or *(a+i).

Now I have a function:

void print_array(int* array, int arraySize){
    for(int i=0; i<arraySize; i++){
       cout<<*(array+i)<<endl;
       cout<<array[i]<<endl;
    }
}

When I pass a[4]={1,2,3,4} into this function using print_array(a,4), for the first line of cout, I fully understand because I use *(a+i) method to access data and a is the pointer I passed.

What I can't understand is: since I pass a pointer a into function, why can I use a in the format of a[i] like the second line of cout? Isn't a a pointer? If a is a pointer why does a[i] work?

This has confused me for a whole day. Any help will be much appreciated!

Rishi
  • 1,387
  • 10
  • 14
Sheen
  • 9
  • 1
  • 3
    a[b] is always exactly identical to `*(a+b)` regardless of what a and b are. – fuz Feb 13 '17 at 12:00
  • 1
    @fuz explained in detail here http://stackoverflow.com/questions/381542/with-c-arrays-why-is-it-the-case-that-a5-5a?rq=1 – Kami Kaze Feb 13 '17 at 12:01
  • I think a[i] will essentially translate to the value at a plus one size of what a points to. – marshal craft Feb 13 '17 at 12:03
  • @i can't agree with your pluses one comment because b will typically be an integer and is incremented by one however the address is incremented by b*size of the type of array. Disregard this comment if I miss some obvious aspect of c++. – marshal craft Feb 13 '17 at 12:06
  • @marshalcraft The pointer already knows the size. `int* a = ...; int* b = a+1` will result in a difference of `sizeof(int)` between the values of `a`and `b`. Using `char* a = ...; char* b = a+1` the addresses will only differ by `sizeof(char)` – Simon Kraemer Feb 13 '17 at 12:11
  • 1
    Oh and because `a[b]` is equivalent `*(a+b)` this again is equivalent to `*(b+a)` and `b[a]`. Allowing you to write `0[a]` instead of `a[0]`: https://godbolt.org/g/fk0hdR – Simon Kraemer Feb 13 '17 at 12:14

4 Answers4

0

Because in effect, while the subscript operator is defined on arrays, what happens is that they decay into pointers for the arithmetic to occur.

Meaning if a is an array, semantically what happens is:

int b = a[i]; => int *__tmp = a; int b = *(__tmp + i);

However, once operator overloading comes into play, then it is no longer true that a[i] == *(a + i). The right hand side may not even be defined.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • That's true in C and in C++ before [CWG 1213](http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1213), but now in C++ `a[i]` and `*(a+i)` have subtle differences when `a` has array type. – cpplearner Feb 13 '17 at 12:02
  • This is a very straight way of thinking(it helps explaining a lot). But I wonder is it defined like that in the standard? (c and c++ if possible?). Because I always thought of this as a array feature that extends to pointers (as the declaration of arrays uses the same brackets) – Kami Kaze Feb 13 '17 at 12:03
  • @cpplearner - That question was tagged C originally, where what I said does hold. Whatever. I'll chalk it up to the OP being a new user. – StoryTeller - Unslander Monica Feb 13 '17 at 12:05
  • @cpplearner - Wait, CWG 1213 added that to make the value categories of the expression clearer. The decay **must still happen**. Because it's equivalent to `*(a + i)` by the standard, and arithmetic **is not** defined for arrays, only pointers. – StoryTeller - Unslander Monica Feb 13 '17 at 12:11
  • @StoryTeller By "that" I mean "you can't in fact use the subscript operator on arrays". – cpplearner Feb 13 '17 at 12:14
  • What CWG 1213 affects is whether `a[i]` (or `*(a+i)`) is an xvalue or lvalue - which (subtly) restricts how they can be used. It doesn't change their equivalence (i.e. `a[i] == *(a + i)` will still test true). – Peter Feb 13 '17 at 12:49
0

This quote from the C++ Standard will make the point clear (5.2.1 Subscripting)

1 A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type “array of T” or “pointer to T” and the other shall have unscoped enumeration or integral type. The result is of type “T.” The type “T” shall be a completely-defined object type.64 The expression E1[E2] is identical (by definition) to *((E1)+(E2)) [Note: see 5.3 and 5.7 for details of * and + and 8.3.4 for details of arrays. —end note], except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

a is an array, not a pointer. They are not the same things. However, the name a can be implicitly converted to a pointer (with the value &a[0]).

For example;

  int main()
  {
       int a[] = {1,2,3,4};
       int *p = a;              //  p now has the value &a[0]

Now, after this partial code snippet, assuming i is an integral value, rules of the language amount to;

  • a[i] is equivalent to *(a + i) which is equivalent to *(&a[0] + i)
  • p[i] is equivalent to *(p + i)

Now, since p is equal to &a[0] this means that a[i], *(a + i), p[i], and *(p + i) are all equivalent.

When calling print_arrat(a, 4) where a is the name of an array, then a is ALWAYS converted to a pointer. This means print_arrat() is always passed a pointer. And this means *(array + i) inside print_arrat() is the same as a[i] in the caller.

Peter
  • 35,646
  • 4
  • 32
  • 74
0

What I can't understand is: since I pass a pointer "a" into function, why can I use "a" in the format of a[i] like the second line of "cout"?

Because subscript operator a[i] is defined for arrays and it is equivalent to *(a+i) by definition.

In the line with cout, you use array[i] however, where array is a pointer. This is also allowed, because the subscript operator is also defined for pointers.

Isn't "a" a pointer?

No. a is an array. array is a pointer.

eerorika
  • 232,697
  • 12
  • 197
  • 326