Implicaciones de la precedencia de operadores en C

I understand that this topic has come up umpteen times but I request a moment.

I have tried understanding this many times, also in context of order of evaluation. I was looking for some explicit examples to understand op. precedence and I found one here: http://docs.roxen.com/pike/7.0/tutorial/expressions/operator_tables.xml What I would like to know is if the examples given there (I have cut-pasted them below) are correct.

1+2*2                  =>  1+(2*2)
1+2*2*4                =>  1+((2*2)*4)
(1+2)*2*4              =>  ((1+2)*2)*4
1+4,c=2|3+5            =>  (1+4),(c=(2|(3+5)))
1 + 5&4 == 3           =>  (1 + 5) & (4 == 3)
c=1,99                 =>  (c=1),99
!a++ + ~f()            =>  (!(a++)) + (~(f()))
s == "klas" || i < 9   =>  (s == "klas") || (i < 9)
r = s == "sten"        =>  r = (s == "sten")

For instance, does 1+2*2*4 es realmente 1+((2*2)*4) or could as well have been, 1+(2*(2*4)) according to C specification. Any help or further reference to examples would be useful. Thanks again.

preguntado el 22 de septiembre de 13 a las 18:09

what prevents you of compiling this and looking at the assembly? -

Tried to Google and opened the page you referenced. Did you read about associativity? -

You need to take into account both precedencia y asociatividad. -

@AndreasGrapentin: Because it would only tell about the implementation, not the standard. -

@o2genum: Yes. But then 'left to right', etc. seems a bit confusing in implications where multiple correct answers are possible -

4 Respuestas

Although those examples come from a different language, I think they are the same as operator precedence in C. In general, you'd be better off using a reference for the C language, such as the C standard, or a summary such as the one in Wikipedia .

However, I don't believe that is actually what you are asking. Operator precedence has no implications for order of evaluation. All operator precedence does is show you how to parenthesize the expression. A C compiler is allowed to evaluate the operations in just about any order it wishes to. It is also allowed to use algebraic identities if it is provable that they will have the same result for all valid inputs (this is not usually the case for floating point calculations, but it is usually true for unsigned integer calculations).

The only cases where the compiler is required to produce code with a specific evaluation order are:

  1. Short-circuit boolean operators && y ||: the left argument must be evaluated first, and in some cases the right argument may not be evaluated;

  2. The so-called ternary operator ?:: the left argument (before the ?) must be evaluated first; subsequently, exactly one of the other two operators will be evaluated. Note that this operator groups to the right, demonstrating that there is no relationship between grouping and evaluation order. That is, pred_1 ? action_1() : pred_2 ? action_2() : pred_3 ? action_3() es el mismo que pred_1 ? action_1() : (pred_2 ? action_2() : pred_3 ? action_3()), pero es pred_1 which must be evaluated first.

  3. El operador de coma ,: the left argument must be evaluated first. This is not the same as the use of the comma in function calls.

  4. Function arguments must be evaluated before the function is called, although the order of evaluation of the arguments is not specified, and neither is the order of evaluation of the expression which produces the function.

The last phrase refers to examples such as this:

// This code has Undefined Behaviour. DO NOT USE
typedef void(*takes_int_returns_void)(int);
takes_int_returns_void fvector[3] = {...}
//...
//...
(*fvector[i++])(i);

Here, a compiler may choose to increment i before or after it evaluates the argument to the function (or other less pleasant possibilities), so you don't actually know what value the function will be called with.

En el caso de los 1+2*2*4, the compiler must generate code which will produce 17. How it does that is completely up to the compiler. Furthermore, if all x, y y z are all unsigned integers, a compiler may compile 1 + x*y*z with any order of multiplications it wants to, even reordering to y*(x*z).

Respondido el 24 de Septiembre de 13 a las 02:09

Thanks for the answer. Paul Griffiths said above that "Binary operators, other than assignment operators, go from left to right when they are of equal precedence". I looked at the standard and could not find the reference to the same. Is it true and I missed something in the standard? - Inactivo

The only place I could find it to be so was on MSDN link. But that still says nothing about the standard. - Inactivo

@user926918: The standard does not explicitly define precedence; rather, it provides an unambiguous grammar. You can derive precedence from the grammar, although the grammar is more accurate. For example: 6.5.6: additive-expression: multiplicative-expression | additive-expression + multiplicative-expression | additive-expression - multiplicative-expression. That shows that in a+b+c, it's not legal to derive b+c como una additive-expression, porque + debe tener un multiplicative-expression on its left. The only legal derivation is a+b + c - luminoso

@user926918: So, if you work your way through all the binary operators, you'll find that ?: and all the assignment operators group to the right. The case of ?: is perhaps the most interesting because it is clear that it evaluates left-to-right, but it groups right-to-left. That's a good demonstration of the lack of relationship between the two concepts. - luminoso

The closest I could get was to find a couple of examples (Eg. 6-7) in 5.1.2.3 Program execution of C99 (n1256.pdf). But these were examples and not formal specification itself. - Inactivo

Most operators have precedence from left to right.This will give a detailed idea about operator precedence :

Presione aquí!

Respondido el 22 de Septiembre de 13 a las 18:09

Binary operators, other than assignment operators, go from left to right when they are of equal precedence, so 1 + 2 * 2 * 4 es equivalente a 1 + ((2 * 2) * 4). Obviously in this particular case 1 + (2 * (2 * 4)) gives the same answer, but it won't always. For instance, 1 + 2 / 2.0 * 4 evalúa a 1 + ((2 / 2.0) * 4) == 5.0 y no a 1 + (2 / (2.0 * 4)) == 1.25.

Order of evaluation is a completely different thing from operator precedence. For one thing, operator precedence is always well-defined, order of evaluation sometimes is not (e.g. the order in which function arguments are evaluated).

Respondido el 22 de Septiembre de 13 a las 23:09

Este es un perfecto tutoriales about operator precedence and order of evaluation. Enjoy!

Respondido el 22 de Septiembre de 13 a las 19:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.