I fatti
Questa è una domanda molto simile a questo , ma qui sto parlando di un caso più generale della regola MISRA-C3 5.0.2 o SEI CERT C EXP00-C (più permissivo).
All'interno di MISRA-C3 I deve utilizzare le parentesi per evitare la precedenza implicita dell'operatore. Quindi il seguente codice è corretto, ma ai miei occhi è molto semplice:
if ((((x * y) + 3) > z) && ((w - 1) <= (42 + (x / (y + z)))))
Nota: mentre stavo scrivendo questa espressione ho dovuto copiarlo / incollarlo nel mio editor di codice per correggere la parentesi mancante perché troppo ingombrante.
Come programmatore esperto userei solo la parentesi per una precedenza non ovvia che potrebbe dipendere dal linguaggio di programmazione che uso. La tabella di precedenza dell'operatore C potrebbe non essere facile da imparare, soprattutto per i nuovi programmatori C e talvolta anche per i miei me stesso quando sono stanco di ore di programmazione nel bel mezzo della notte.
La mia regola empirica è:
Parenthesis shall be used for explicit operator precedence with all operators except the logical and (
&&
) and or (||
), and the 4 basic operations (* / + -
).
L'espressione sopra può quindi essere semplificata in questo modo:
if ((x * y + 3) > z && (w - 1) <= (42 + x / (y + z)))
Quest'ultima espressione sembra molto più facile da leggere e posso vedere a colpo d'occhio se mi manca una parentesi.
Inoltre, poiché l'operatore uguale ( =
) rientra anche nella regola MISRA. Gli sviluppatori dovrebbero anche scrivere z = (a * b)
e non z = a * b
.
La storia dietro
Lavoro in un'azienda in cui gli sviluppatori sono lontani dall'esperienza nella programmazione in C nonostante tutti facciano programmi in C per oltre 10-15 anni. Continuano ad aggiungere commenti inutili x = 2; // Assign x with 2
ovunque e afferma che la prima espressione che ho scritto è molto più leggibile perché nessun essere umano può imparare a memoria la precedenza degli operatori. Di solito usano commenti, parentesi o dichiarazioni avanzate ovunque piuttosto che usare il loro buon senso per mantenere il flusso di lettura chiaro e comprensibile.
Stavo cercando di insegnare loro la bellezza della programmazione in cui il programmatore deve raccontare una storia e mantenere il flusso cristallino evitando cose inutili che mettono ovunque perché una volta qualcuno gli ha detto di farlo.
Oggi mi sto interrogando e mi chiedo se ho ragione o torto su questa cosa da parentesi. Forse la prima espressione è più comprensibile della seconda per la maggior parte delle persone.
Esempi
if ((i > LENGTH) && (((a * b) + c) > (d + e))) // Bad
if (i > LENGTH && a * b + c > d + e) // Good
y = ((x * y) + 1); // Bad
y = x * y + 1; // Good
La domanda
La mia regola empirica (riquadro giallo sopra) è una buona regola? La regola 5.0.2 di MISRA C3 è solo di consulenza e CERT-C è più nella mia direzione.