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:

<br />#include "stdio.h"     /* printf */<br />#include "string.h"     /* strcat */<br />#include "stdlib.h"     /* strtol */<br /><br />unsigned char *p;<br />unsigned char *ps;<br />unsigned char  a;<br />unsigned char  b;<br />unsigned char  c;<br /><br />unsigned char  x;<br />unsigned char  y;<br />unsigned char  z;<br />typedef struct<br />{<br />  unsigned char h;<br />  unsigned short r;<br />} ms;<br />ms *m;<br />unsigned char  result;<br />unsigned char  temp;<br />unsigned char  flag;<br />unsigned char  low;<br />unsigned char  high;<br /><br />const char *byte_to_binary(int x)<br />{<br />    static char b[9];<br />    b[0] = '';<br /><br />    int z;<br />    for (z = 128; z > 0; z >>= 1)<br />    {<br />        strcat(b, ((x & z) == z) ? "1" : "0");<br />    }<br /><br />    return b;<br />}<br /><br />int main()<br />{<br /><br />  *p++;           /* equivalent to *(p++); */<br />  /*(char)!-˜*++p; */  /* applied using an inside out order */<br />  /* m<- ps="">m;*/   /* ’->’ is an unary operator */<br />  a = b = c;          /* equivalent to a = (b = c); */<br />  temp = x + y + z;   /* equivalent to (x + y) + z */<br />  flag =2;<br />  if (flag & 2) /* clear meaning */<br />  {<br />    printf("flag = %dn", flag);<br />  }<br />  if (flag & 2 != 0) /* more explicit? */<br />  {<br />    printf("flag = %dn", flag);<br />  }<br />  if (flag & (2 != 0)) /* unfortunately:<br />                          * ’!=’ binds stronger... */<br />  {<br />   printf("flag = %dn", flag);<br />  }<br /><br />  low = 1;<br />  printf("low = %sn", byte_to_binary(low));<br />  high = 8;<br />  printf("high = %sn", byte_to_binary(high));<br /><br />  result = high << 4 + low; /* hmm ... */<br />  printf("result = %sn", byte_to_binary(result));<br /><br />  low = 1;<br />  high = 8;<br />  result = high << (4 + low); /* probably not intended */<br />  printf("result = %sn", byte_to_binary(result));<br /><br />  low = 1;<br />  high = 8;<br />  result = (high << 4) + low; /* probably the<br />                               * correct implementation */<br />  printf("result = %sn", byte_to_binary(result));<br /><br />  a = 3;<br />  a++;<br />  printf("a = %dn", a);<br />  ++a;<br />  printf("a = %dn", a);<br /><br />  b = 3;<br />  b--;<br />  printf("b = %dn", b);<br />  --b;<br />  printf("b = %dn", b);<br /><br />}<br />

Rezultat:

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

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 <br />                                * sunt executate primele */<br />

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!

De admin

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *


The reCAPTCHA verification period has expired. Please reload the page.