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!