The problem: it is too easy to write incorrect code with the unary "-", e.g.
  "- i / 2" (which means "(- i) / 2")
when one really wants "- (i / 2)". The reasons are:

1. Whereas the binary "-" has a lower precedence than the binary "*" (multiply)
and "/" (divide), the unary "-" has a higher precedence. It is easy to forget
this difference, in particular because the same symbol is used with two
different precedences. For instance, the expressions "0 - i / 2" and "- i / 2"
look the same, but the former corresponds to "0 - (i / 2)" and the latter
corresponds to "(- i) / 2".

2. Mathematically (in a ring), the precedence of the unary "-" (for the
opposite) vs "*" (multiply) does not matter since the result does not depend on
the precedence, so that it is never explicited in practice and what the writer
of a math expression really thinks depends on the context.

The following code shows such a problem that can occur in practice: the unary
"-" in "k = - i / 2" yields an integer overflow, hence undefined behavior. The
user may not be aware of it. And the fact that this bug is hidden with -O2
optimizations makes it worse. For instance, when compiling this code without
optimizations, I get:
  j = 1073741824
  k = -1073741824
(which is not the intended result). With -O2 optimizations, I get:
  j = 1073741824
  k = 1073741824

Adding the following warnings could avoid bugs like this one:
  warning: suggest parentheses around unary - in operand of *
  warning: suggest parentheses around unary - in operand of /

Note: such warnings should also apply to floating-point expressions as they can
be affected in the rounding directions FE_DOWNWARD and FE_UPWARD.

#include <stdio.h>
#include <limits.h>

int main (void)
{
  int i, j, k;

  i = INT_MIN;
  j = 0 - i / 2;
  k = - i / 2;
  printf ("j = %d\n", j);
  printf ("k = %d\n", k);
  return 0;
}


-- 
           Summary: Request warnings about the precedence of the unary -
                    over the binary * and /
           Product: gcc
           Version: 4.3.1
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: vincent at vinc17 dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36588

Reply via email to