2016-07-29 22 views
-1

Ich bekomme falsche Asm-Code für den folgenden Test-Code aus dem C-Compiler. Liegt das an undefiniertem Verhalten?Reihenfolge der Auswertung: undefiniertes Verhalten? oder Kompilierer defekt?

void SimulatedTest(void) 
{         
    if ((a) || (b && c || d) == 1) 
    { 
     i = 2; 
    } 
    else 
    { 
     i = 4; 
    } 
} 

Welche Standard sagt:

6.5.16 Zuordnung Betreiber

Die Reihenfolge der Auswertung der Operanden ist nicht spezifiziert. Wenn ein Versuch gemacht wird, um das Ergebnis eines Zuweisungsoperator zu ändern oder den Zugriff auf nach der nächsten Sequenz Punkt das Verhalten ist nicht definiert

C Operator Präzedenz Regel

  1. ()
  2. ==
  3. || & &

Für den Problemfall: if ((a) || (b & & c || d) == 1) Compiler den Ausdruck in der folgenden Reihenfolge auswertet und erzeugt falsche Code

1. (b & & c || d) -> R1

2.R1 == 1 -> R2

3. (a) || R2

jedoch Compiler richtigen Code für die unten Fällen

Case1 erzeugt:. Wenn es keine relationale '==' Operation

if ((a) || (b && c || d))//compiler generates expected code 

Case2: Wenn Klammerung ist

if (((a) || (b && c || d)) == 1)//compiler generates expected code 

Case3 für die logische ODER-Verknüpfung hinzugefügt: keine

zwischen Operationen verwendet Klammern
if (a || b && c || d == 1)//compiler generates expected code 

Möchten Sie wissen, ob der Problemfall in undefinierte Verhalten Kategorie fällt oder nicht.

Grüße,

Mac

+1

Nur eine Bemerkung über Ihre _C Operator Precedence rule_: '&&' hat eine höhere Priorität als '||', also müssen sie nicht in der gleichen Zeile sein – Garf365

+0

Sie scheinen einen Satz Klammern zu haben, wenn Sie wollen Erhalten Sie Ihr 'erwartetes Ergebnis' – Shark

+0

Fragen, die Debugging-Hilfe suchen ("warum funktioniert dieser Code nicht?") müssen das gewünschte Verhalten, ein spezifisches Problem oder einen Fehler und den kürzesten Code enthalten, der in der Frage selbst reproduziert werden muss. Fragen ohne eine klare Problemstellung sind für andere Leser nicht nützlich. Siehe: Erstellen eines minimalen, vollständigen und überprüfbaren Beispiels. – Olaf

Antwort

7

Equality Operator == höhere Priorität als die logische oder || Operator hat. Daher ist der Compiler korrekt und es gibt kein undefiniertes Verhalten.

Die Auswertung ist identisch mit:

a || ((b && c || d) == 1) 
0

dieses:

if ((a) || (b && c || d) == 1) 

wird die Ergebnisse der || mit einer ganzen Zahl zu vergleichen, das ist nicht, was Sie tun möchten.

die Rangordnung der logischen Operatoren gegeben, die nicht immer ist das, was die Menschen erwarten, dann ist es in der Regel in Klammern zu werfen, um die Dinge klarer zu dem Lese sichersten, so

if ((a) || ((b && c) || d) == 1) 

oder

if ((a) || (b && (c || d)) == 1) 

mit der && oder ||

und je nachdem, was Sie erwarten, dass der == zu vergleichen mit (wenn Sie wirklich wollen das tun, was ich bezweifle)

if ((a) || ((b && c || d) == 1)) 

oder

if (((a) || (b && c || d)) == 1) 

Aber der Compiler richtig kompiliert. Es ist einfach nicht sehr offensichtlich, was mit dem menschlichen Verstand geschehen soll.