0

I'm currently learning about pointers in C, but I'm a little confused about how right to left associativity works with regards to incrementing a pointer versus incrementing the value being pointed at.

It is understood that ++ and * are both right to left associative in C.

I don't see how *s++ moves the array ahead 1, yet (*s)++ increments the value being pointed at but doesn't move the array ahead.

For example:

#include <stdio.h>

int main(){
    char c[20] = "Help";
    char *s;
    s = c; 
    printf("init: %s\n",s); // Help
    ++*s;
    printf("++*s: %s\n",s); // "Ielp" ascii increment of first element
    ++(*s);
    printf("++(*s): %s\n",s); // "Jelp" ascii increment of first element
    *s++;
    printf("*s++: %s\n",s); // "elp" moves to next element in array
    (*s)++;
    printf("(*s)++: %s\n",s); // "flp" ascii increment of current element
    *(++s);
    printf("*(++s)\n: %s\n",s); // "lp" moves to next element
    *++s;
    printf("*++s\n: %s\n",s); // "p" moves to next element
    return 0;
}

For the code above, can someone help explain what is going on AND why?

Thanks for taking a look.

bsheps
  • 1,438
  • 1
  • 15
  • 26
  • Associativity only matters when no parentheses are present. When they are, expressions in parentheses are always evaluated first. Similar reason why `7-3+2=6` but `7-(3+2)=2`. – dxiv Dec 01 '20 at 03:37
  • 1
    Also, `*s++` evaluates to `*(s++)` not because of associativity, but because the postfix increment `++` has strictly [higher precedence](https://en.cppreference.com/w/c/language/operator_precedence) than the dereference `*` operator. – dxiv Dec 01 '20 at 03:45
  • Voting to close as a duplicate of [Pointer expressions: \*ptr++, \*++ptr and ++\*ptr](https://stackoverflow.com/questions/18481740/pointer-expressions-ptr-ptr-and-ptr) which has several detailed answers. – dxiv Dec 01 '20 at 03:53
  • 1
    Thanks @dxiv! The first answer on that question is the perfect explanation. For whatever reason google and SO search wouldn't reveal that great explanation. – bsheps Dec 01 '20 at 04:10

1 Answers1

2

As helped by dxiv and John Bode,

When parsing an expression, an operator which is listed on some row will be bound tighter (as if by parentheses) to its arguments than any operator that is listed on a row further below it. For example, the expression *p++ is parsed as *(p++), and not as (*p)++.

In the above expression the point worth noted is ++ is a postfix operator whose precedence(or priority) is greater than *(unary operator)

Operators that are in the same cell (there may be several rows of operators listed in a cell) are evaluated with the same precedence, in the given direction. For example, the expression a=b=c is parsed as a=(b=c), and not as (a=b)=c because of right-to-left associativity.

other example where associativity comes into picture is *++p

here * and ++(prefix operator) are having same precedence, so they will be evaluated as right to left.

IrAM
  • 1,720
  • 5
  • 18
  • 1
    The right-to-left associativity plays no role into why `*s++` is being evaluated as `*(s++)`. That follows from the precedence of the operators alone. – dxiv Dec 01 '20 at 03:57
  • @dxiv, but [here](https://en.cppreference.com/w/c/language/operator_precedence) `*` and `++` have same precendece , am i wrong? – IrAM Dec 01 '20 at 04:04
  • Also there is para there saying _Operators that are in the same cell (there may be several rows of operators listed in a cell) are evaluated with the same precedence, in the given direction. For example, the expression a=b=c is parsed as a=(b=c), and not as (a=b)=c because of right-to-left associativity._ – IrAM Dec 01 '20 at 04:08
  • 1
    In the table at your link, *postfix* `++` has precedence 1, lower than precedence 2 for the dereference `*` operator. In fact that's precisely the example given at that link, read the paragraph "*when parsing an expression ...*" below the table. – dxiv Dec 01 '20 at 04:09
  • 1
    @IrAM: *Prefix* `++` has the same precedence as unary `*`, so `*++p` is affected by associativity. Postfix `++` has higher precedence than unary `*`, so `*p++` is evaluated as `*(p++)` irrespective of associativity. – John Bode Dec 01 '20 at 04:10
  • @JohnBode, yeah got it, got little confused there – IrAM Dec 01 '20 at 04:15
  • @IrAM Thanks for the explanation. I also learned from the discussion here in the comments. Marking as correct. – bsheps Dec 02 '20 at 00:49
  • All credit goes to @dxiv and JohnBode – IrAM Dec 02 '20 at 03:19