4

Array subscript [] in C is listed as having higher precedence than prefix increment.

Having following simple program:

#include <stdio.h>
int main()
{
   char testArr[] = "asdfgh";
   int a = 0; 
   printf("element is %c\n",testArr[++a]);
}

Why is s printed instead of a? The way as I see things, [] should have been applied first. Which means that the first element 0 of the testArr should have been displayed and not the element 1.

Tormund Giantsbane
  • 355
  • 1
  • 4
  • 12
  • 1
    `++a` is an expression with the **new** value of a. – wildplasser Aug 30 '17 at 22:07
  • @Schwifty Szechuan comment should be the answer, just saying. – savram Aug 30 '17 at 22:08
  • @savram Removed* it was actually incorrect :) (Also it wouldn't of answered the question, just pointing something out). `testArr[++a]` is equivalent to `testArr[(++a)]` and `testArr[a++]` is equivalent to `testArr[(a++)]`. – George Aug 30 '17 at 22:11
  • the precedence only matters if the two things apply to the same variable. For example, in mathematics, parenthesis is higher precedence than addition but when you see (a+b) you still do the addition first. So for ++a[i] you need to worry about precedence but for a[++i] you don't because the ++ has to be done first anyway. – Jerry Jeremiah Aug 30 '17 at 22:11
  • @Schwifty Szechuan How was it incorrect? The ++ operator has higher precedence than the [] operator as you said. Not that it matters because it calculates what's inside the [] before doing the access regardless of the precedence, but still it points out that the OP's question is malformed – savram Aug 30 '17 at 22:18
  • 4
    You're confusing *precedence* with *order of evaluation* – M.M Aug 30 '17 at 22:22
  • 1
    An example where this precedence is relevant would be `++testArr[a]` - the precedence means that this is `++(testArr[a])` and not `(++testArr)[a]` – M.M Aug 30 '17 at 22:23
  • @savram Only the suffix increment and decrement operators, and the function call operator have a higher precedence than the subscript operator. Easy to miss the difference at a glance of the [page](http://en.cppreference.com/w/c/language/operator_precedence) I linked. – George Aug 30 '17 at 22:25
  • I misread suffix/postfix for suffix/prefix lol you're right – savram Aug 30 '17 at 22:33

5 Answers5

4

The subscript operator is defined the following way

postfix-expression [ expression ]

So to apply the subscript operator the compiler shall calculate the expression in the square braces (along with the postfix expression) to get the value of the expression.

From the C Standard (6.5.2.1 Array subscripting)

2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).

To make it more clear consider a simple code snippet

int i = 0;
int j = 1;

printf("element is %c\n",testArr[i + j]);

How the compiler can determine the index without calculation the expression i + j?

That is the subscript operator is composed from two subexpressions that are evaluated to get their values.

Your question is reasonable if to consider the following expression

++testArr[++a]

or even the following expression

++a[testArr]

In this case due to the operator precedence the first expression is equivalent to

++( testArr[++a] )

and the second one is equivalent to

++( a[testArr] )

So the subscript operator including its subexpression in square braces ++a or testArr evaluates first and after that the unary operator evaluates.

On the other hand if to use the postfix increment like

a++[testArr]

then the expression is equivalent to

( a++[testArr] )

that is it is just the subscript operator that follows its own definition form

        a++        [  testArr   ]    
postfix-expression [ expression ]
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

When you write

testArr[++a]

C will look at the index in the array given by the value of the expression ++a. Regardless of the operator precedence between [] and ++, the value of the expression ++a is one greater than the value a had before the expression was initially evaluated, which is why you're seeing the character at index 1 rather than the character at index 0.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
1

in plain english: [a++] - means [a+1] operation will be done after all other operations, [++a] - means [a+1] operation will be done before all other operations.

Halina V
  • 49
  • 1
  • 6
0

Expressions can consist of multiple operations and their operands. By using parenthesis one can define in which order these operations shall execute. Operator precedence defines the order of operations if there is no order defined already via parenthesis.

In your case, ++a is a child expression of the [] operand so no matter what you put inside [] it will be evaluated before evaluating the [] operand.

ben
  • 5,671
  • 4
  • 27
  • 55
  • 1
    Note that side-effects of the child expression aren't sequenced-before the parent expression or any other child expressions in this case – M.M Aug 30 '17 at 22:28
  • Thanks all for the answers.Vlad from Moscow answer I liked most. – user1866843 Sep 01 '17 at 13:12
  • @user1866843 Then you should consider [accepting that answer](https://stackoverflow.com/help/accepted-answer). – dbush Sep 01 '17 at 18:13
0

So, from what Vlad posted, it seems that the compiler evaluates the expression: testArr[++a] as *((testArr)+(++a))

However, for multidimensional arrays, following program prints 2:

#include<stdio.h>

int main()
{
int a[3][3]={0,1,2,3,4,5,6,7,8};
int index=0;
printf("element is %d\n",a[index++][++index]);
}

If anyone can explain this, using C standard, would be even better. I have looked on C standard and is not mentioning anything about subscripting for multi-dimensional arrays.