Precedenţa şi asociativitatea operatorilor

 Precedenţa şi asociativitatea operatorilor

Limbajul C este unul dintre cele mai complexe limbaje când vine vorba de precedenţa operatorilor. Exista 15 de nivele diferite de precendenţă .
Precendenţa se referă la ordinea de evaluare a expresiilor şi depinde de doua lucruri:
- Operatorii au nivele de precendeţă diferite.
- Operatorii au asociativitate diferită de stânga sau de dreapta.

Operator Associativity
( ) [ ] -> . ++’postfix’ --’postfix’ Left
! ˜ ++ -- + - (type) * & sizeof Right
* / % Left
+’binary’ -’binary’ Left
<< >> Left
< <= > >= Left
== != Left
& Left
ˆ Left
| Left
&& Left
|| Left
?: Right
assignments Right
, Left

Exemplu:


#include "stdio.h"     /* printf */
#include "string.h"     /* strcat */
#include "stdlib.h"     /* strtol */

unsigned char *p;
unsigned char *ps;
unsigned char  a;
unsigned char  b;
unsigned char  c;

unsigned char  x;
unsigned char  y;
unsigned char  z;
typedef struct
{
  unsigned char h;
  unsigned short r;
} ms;
ms *m;
unsigned char  result;
unsigned char  temp;
unsigned char  flag;
unsigned char  low;
unsigned char  high;

const char *byte_to_binary(int x)
{
    static char b[9];
    b[0] = '\0';

    int z;
    for (z = 128; z > 0; z >>= 1)
    {
        strcat(b, ((x & z) == z) ? "1" : "0");
    }

    return b;
}

int main()
{

  *p++;           /* equivalent to *(p++); */
  /*(char)!-˜*++p; */  /* applied using an inside out order */
  /* m<- ps="">m;*/   /* ’->’ is an unary operator */
  a = b = c;          /* equivalent to a = (b = c); */
  temp = x + y + z;   /* equivalent to (x + y) + z */
  flag =2;
  if (flag & 2) /* clear meaning */
  {
    printf("flag = %d\n", flag);
  }
  if (flag & 2 != 0) /* more explicit? */
  {
    printf("flag = %d\n", flag);
  }
  if (flag & (2 != 0)) /* unfortunately:
                          * ’!=’ binds stronger... */
  {
   printf("flag = %d\n", flag);
  }

  low = 1;
  printf("low = %s\n", byte_to_binary(low));
  high = 8;
  printf("high = %s\n", byte_to_binary(high));

  result = high << 4 + low; /* hmm ... */
  printf("result = %s\n", byte_to_binary(result));

  low = 1;
  high = 8;
  result = high << (4 + low); /* probably not intended */
  printf("result = %s\n", byte_to_binary(result));

  low = 1;
  high = 8;
  result = (high << 4) + low; /* probably the
                               * correct implementation */
  printf("result = %s\n", byte_to_binary(result));

  a = 3;
  a++;
  printf("a = %d\n", a);
  ++a;
  printf("a = %d\n", a);

  b = 3;
  b--;
  printf("b = %d\n", b);
  --b;
  printf("b = %d\n", b);

}

Rezultat:


/precendata.exe
flag = 2
result = 00000001
result = 00001000
result = 00000000
result = 00000000
result = 10000001
a = 4
a = 5
b = 2
b = 1

Regula de bază pentru a evita problemele este :

Fiecare subexpresie a unei expresii mai complicate ar trebui flancată de parenteze.
Exemplu:
  r = (hi << 4) + (low >> 2); /* operatiile flancate de paranteze 
                                * sunt executate primele */

MISRA

E bine să ne bazăm şi pe cele două reguli MISRA:
MISRA-C:2004, Rule 12.1: Limited dependence should be placed on C’s operator precedence rules in expressions

MISRA-C:2004, Rule 12.2: The value of an expression shall be the same under any order of evaluation that the standard permits

Nu uitaţi , Keep It Simple!

Etichete

Afișați mai multe

Arhiva

Afișați mai multe