How are operators with the same precedence in C evaluated? - c

In the context of C operators precedence. In reality, the following code will be evaluated as follows:
int32_t * result = (int32_t *) addr_base + offset;
|
|
↓
int32_t * result = ((int32_t *) addr_base) + offset;
However, what I see in the table bellow is that cast and + should be evaluated from right to left. In other words, in my example + is right to cast, so I would expect that the first statement above will be evaluated like this:
int32_t * result = (int32_t *) (addr_base + offset);
As + is on the right side of cast (so more priority according to the table).
Why is that actually happening?

The + in row 2 is the unary plus operator. This is similar to the unary negation operator (e.g. x = -y)
The operator for addition is in row 4 and has a lower precedence than the cast.
In case two operators have the same precedence the order is given by the Associativity (left to right or right to left)

The cast operator has higher precedence than addition, so that's why the operand is grouped with the cast operator.
Unary plus has the same precedence as cast. If you were to use those in the same expression, the associativity would go from right to left.

A cast operator has the same precedence as a unary + operator, but the + operator in (int32_t) addr_base + offset is a binary + operator, which has lower precedence.
A unary operator is one with only one operand. In x = -y;, the - is a unary operator. We can also write x = +y;, where the + is a unary operator, but this is rarely done since it is largely superfluous.
A binary operator is one with two operands. In x = y + z, the + is a binary operator.

Although unary plus has the same precedence as casts, the expression in question involves binary +, which is two rows lower in the precedence table. So
(int32_t *) addr_base + offset
is unambiguously parsed as
((int32_t *) addr_base) + offset

Related

C Operators and Precedence

I'm using C language, for the below code:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int num1=0;
int res = ++num1 && num1++;
printf("%d\t%d\n",num1,res);
}
In the above code I get output as 2 1. I think the output should be 2 0.
Please correct me if wrong, to solve this statement, the num1++(0) would be executed first due to highest precedence and then ++num1(2) would be executed and then at last && will be preformed because it has the lowest precedence.
Please comment how is this statement getting executed.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence, but if that is true then according to the associativity rule again num1++ should be executed first(right to left) which should again lead to answer as 2 0.
In the expression used as an initializer
int res = ++num1 && num1++;
there is a sequence point for the operator &&.
From the C Standard (6.5.13 Logical AND operator)
3 The && operator shall yield 1 if both of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
and
4 Unlike the bitwise binary & operator, the && operator guarantees
left-to-right evaluation; if the second operand is evaluated, there is
a sequence point between the evaluations of the first and second
operands. If the first operand compares equal to 0, the second operand
is not evaluated.
At first the left operand of the operator is evaluated and as a result num1 will be equal to 1 due to the unary (prefix) increment operator. As the sub-expression is not equal to 0 then the second operand is evaluated. Its value is the value before incrementing that is 1. As this second operand is also unequal to 0 then the whole expression is evaluated to the logical true and its value is 1 (see the first quote from the C Standard).
This value 1 is assigned to the variable res while the variable num1 after the postfix increment will be equal to 2.
So you will have that after this declaration res is equal to 1 and num1 is equal to 2.
Lots of misconceptions here. First of all, operator precedence states the order of parsing, not the order of execution. There are two related but different terms, operator precedence and order of evaluation.
See What is the difference between operator precedence and order of evaluation?.
Once you understand order of evaluation, the && operator specifically comes with well-defined sequencing, which isn't normally the case for C operators. It guarantees a left-to-right order of evaluation. C17 6.5.14/4:
Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the
second operand is evaluated, there is a sequence point between the evaluations of the first
and second operands. If the first operand compares unequal to 0, the second operand is
not evaluated.
Normally, you wouldn't be able to wild and crazy things with the ++ operator mixed with other operators, but the above && rule makes it possible in this specific case.
See Why can't we mix increment operators like i++ with other operators? It explains sequencing/sequence points.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence,
They don't, prefix ++ takes precedence over postfix (and other unary operators). So associativity does not apply.
Please correct me if wrong, to solve this statement, the num1++(0) would be executed first due to highest precedence and then ++num1(2) would be executed and then at last && will be preformed because it has the lowest precedence.
Precedence only controls which operators are grouped with which operands - it does not affect the order in which expressions are evaluated.
The &&, ||, ?:, and comma operator all force left-to-right evaluation - the left operand is fully evaluated (and any side effects applied) before the right operand. && and || both short circuit - for &&, the right operand will be evaluated only if the left operand is non-zero.
The unary (prefix) ++ operator yields the current value of the operand plus 1, so the result of ++num1 is 1. As a side effect the value in num1 is incremented. Since this result is non-zero, num1++ is also evaluated. The postfix ++ operator yields the current value of the operand, so the result of num1++ is 1. As a side effect the value in num1 is incremented.
The result of an && expression is 1 if both operands are non-zero, 0 otherwise.
It's roughly equivalent to writing
tmp = num1 + 1;
num1 = num1 + 1;
res = 0;
if ( tmp != 0 )
{
if ( num1 != 0 )
{
res = 1;
}
}
num1 = num1 + 1;
So the result of ++num1 && num1++ is 1, and the value stored in num1 at the end of it is 2.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence,
That is very wrong and you should stop using those tutorials immediately. Postfix operators have higher precedence than unary operators - *a++ is parsed as *(a++), ++a[i] is parsed as ++(a[i]), etc. An expression like ++i++ would be parsed as ++(i++), but you can't write such an expression in C - the result of i++ isn't an lvalue and cannot be the operand of a unary ++ like that.

how the expression *p++ and ++*p works differently

#include<stdio.h>
int main()
{
int a[2]={10,4};
int *k;
int *j;
j=a;
k=j;
printf("j=%d,k=%d\n\n",*j,*k);
*j++;
++*k;
printf("j=%d,k=%d",*j,*k);
return 0;
}
The output is:
j=10 k=10
j=4 k=11
I thought that it should have same result but this is not the case.
I wished to ask what is causing this difference. I didn't got the reason behind it.
You need to dig out your operator precedence table.
*p++ is evaluated as *(p++)
++*p is evaluated as ++(*p)
The second one is due to the prefix ++ having the same precedence as pointer dereference * so associativity (which is from right to left for those operators) comes into play.
For completeness' sake, *(p++) dereferences the current value of p, and p is increased by one once the statement completes. ++(*p) adds 1 to the data pointed to by p.
You have two things going on here:
The different semantics between prefix and postfix ++;
Different precedence of prefix and postfix operators.
Postfix operators have higher precedence than unary (prefix) operators, so the expression *p++ is parsed as *(p++) - you're applying the * operator to the result of p++. By contrast, the prefix ++ operator and unary * have the same precedence, so the expression ++*p is parsed as ++(*p) - you're applying the ++ operator to the result of *p.
Also remember that prefix and postfix ++ have slightly different behavior. Both increment their operand as a side effect, but the result of postfix ++ is the current value of the operand, while the result of prefix ++ is the value of the operand plus 1.

Is there any operator in c which is both unary and binary?

Is there any operator in c which is both unary and binary ? This question was asked in one of the interview.
The asterisk (*) can be used for dereferencing (unary) or multiplication (binary).
The ampersand (&) can be used for referencing (unary) or bitwise AND (binary).
The plus/minus signs (+/-) can be used for identity/negation (unary) or addition/subtraction (binary).
But, as others pointed out, those are symbols shared by different operators. Each of those operators have only one n-arity.
No, there isn't. Every operator is either unary, binary, or ternary.
Some unary and binary operators happen to use the same symbol:
* for dereference and multiplication
- for negation and subtraction
+ for identity and addition
& for address-of and bitwise "and"
But unary and binary * are still distinct operators that happen to be spelled the same way.
What I think only . operator is both unary and binary in C (not specified in standard):
.:- Unary: In designators of structures- {.meber1 = x, .member3 = z} (C99 and latter). Binary: Accessing structure members.
There is no operator in C which is unary and binary as well.
Symbols, like +, -, * and &, are used as unary and binary operators but then these symbols are treated as different operators:
+, - Unary: i = -1 j = +1. Binary: i = i+1, j = j+1
* Unary: Dereference operator. Binary: Multiplication operator.
& Unary: Reference operator. Binary: Bitwise AND operator.

Precedence of operators in RPN

While calculating postfix expression in C, if our token is an operator we have to place it the stack in such a way that it's has the highest priority.
My question is among the operators *, /, %, which has the highest priority.
Do we need to consider associativity as well ? Since all these operators have LEFT-TO-RIGHT associativity, will / get higher preference over * ?
Precedence usually only applies to infix notations. Postfix (and Prefix) notations are usually considered to explicitly specify which operands are associated with which operator. Precedence only comes into play when there is ambiguity in the parsing, which is not the case in postfix notation.
The precedence question that arises in an infix expression
4 * 5 + 3 / 12
simply doesn't exist after conversion to an RPN form
4 5 * 3 + 12 /
or a prefix form
(/ (+ (* 4 5) 3) 12)
.
There is some possibility for confusion when considering something like the Shunting-Yard Algorithm which can be used to generate an RPN representation from -- or directly evaluate -- an infix expression. It deals with operator precedence by deferring operators onto a secondary stack until a lower precedence operator forces it to be popped and evaluated (or output).
Operators *, /, % are same in precedence and there associativity is left to right. So an expression like:
a * b / c /* both operators have same precedence */
is same as:
(a * b) / c
Similarly an expression like:
a / b * c /* both operators have same precedence */
is same as:
( a / b ) * c
So even operators are same in precedence, but suppose if they appears in an expression(without parenthesis) then left most operator has higher precedence because of left to right associativity.
Note Conceptually we use parenthesis in an expression to overwrite precedence of operators, so although expression: a / b * c is same as: (a / b) * c but we can force to evaluate * first using ( ) by writing expression as a / ( b * c). What I means to say if you have confusion in operator precedence while writing code use parenthesis.
EDIT:
In POSTFIX and PREFIX form don't use parenthesis ( ). Precedence of operator are decided in order of there appearance in expression, So while evaluating an expression its not need to search next operation to perform - and so evaluation becomes fast.
While in INFIX expression precedence of operators can be overwritten by brackets ( ). Hence brackets are there in infix expression - and it need to search which operation to perform next e.g. a + b % d - and evaluation of expression is slow.
That is the reason conversion are useful in computer science.
So compiler first translates an infix expression into equivalent postfix form(using grammar rules) then generates target code to evaluate expression value. That is the reason why we study postfix and prefix form.
And according to precedence and associativity rules the following expression:
a * b / c /* both operators have same precedence */
will be translates into:
a b * c /
And expression
a / b * c /* both operators have same precedence */
will be translated into
a b / c *
My question is among the operators *, /, %, which has the highest priority.
They are equal, just as + and - (binary) are equal.
Do we need to consider associativity as well?
Yes, for example 1 + 2 + 3 needs to become (1 + 2) + 3, i.e. 1, 2, ADD, 3, ADD, as opposed to 1, 2, 3, ADD, ADD.
Since all these operators have LEFT-TO-RIGHT associativity, will / get higher preference over * ?
Associativity doesn't have anything to do with precence. The question doesn't make sense.
But if you're just calculating an existing RPN expression, as your title says, I don't know why you're asking any of this. You just push the operands and evaluate the operators as they occur. Are you really asking about translation into RPN?

Why is *p++ different from *p += 1?

Consider:
void foo1(char **p) { *p++; }
void foo2(char **p) { *p += 1; }
and
char *s = "abcd";
char *a = s;
foo1(&a);
printf("%s", a); //abcd
but if I use foo2() instead of:
char *a = s;
foo2(&a);
printf("%s", a); //bcd
Can someone explain it?
The key is the precedence of the += and the ++ operator. The ++ has a higher precedence than the += (in fact, assignment operators have the second lowest precedence in C), so the operation
*p++
means dereference the pointer, then increment the pointer itself by 1 (as usually, according to the rules of pointer arithmetic, it's not necessarily one byte, but rather sizeof(*p) regarding the resulting address). On the other hand,
*p += 1
means increment the value pointed to by the pointer by one (and do nothing with the pointer itself).
Precedence. The postfix ++ binds tighter than the prefix * so it increments p. The += is at the low end of the precedence list, along with the plain assignment operator, so it adds 1 to *p.
Precedence of prefix ++ and * is same. Associativity of both is right to left. Precedence of postfix ++ is higher than both * and prefix ++. Associativity of postfix ++ is left to right.
Let's start with *p += 1
I will try to answer this from a bit of a different angle... Step 1 Let's look at the operators and the operands: In this case it is one operand (the pointer p), and we have two operators, in this case * for dereferencing and += 1 for increment. Step 2 which has the higher precedence * has higher precedence over +=
*P++
This one is a bit trickier... maybe even wicked
Again we have one operand (p the pointer) and two operators, only now the * for dereference and ++ post increment are of the same precedence. (In some tables the ++ in a post is a higher precedence.)
Step 1 Let's look at the operators and the operands: In this case it is the operand, and you have two operators, in this case * for dereferencing and ++ for increment. Step 2 which has the higher precedence? ++ has higher precedence over * Note: even if they have the SAME precedence they associate right to left, again, the ++ is before *
Step 3 (the tricky part...) Where is ++ ? it is to the right side of the operand, which means POST Increment In this case, the compiler take a 'mental note' to perform the increment AFTER it is done with all the other operators...
What after means? It means that it will only apply the increment as the very very very last step before the next ';' so it will be done with all other operators that are on the same 'line'
note: if it was *++p then it will do it BEFORE any other operator on the same line so in this case, it is as equivalent to taking two of the processor's register, one will hold the value of the dereferenced *p and the other will hold the value of the incremented p++, the reason in this case there are two, is the POST activity... This is where in this case it is tricky, and it looks like a contradiction. One would expect the ++ to take precedence over the *, which it does, only that the POST means that it will be applied only after ALL other operands, BEFORE the next ';' token...
Like I said, the tricky part is that any increment that is to the right of an operand will be set aside, and will be applied as the LAST operation before it moves on to the next line...

Resources