2010-12-08 17 views
7

In einen Code wie diesen in unserer Code-Basis gestoßen ... was mich besorgt machte.Rückgabewert aus lokalem Bereich?

int foo(int a); // Forward declaration. 

int baz() { 
    int result = { 
     int a = dosomestuff(); 
     foo(a); 
    } ? 0 : -1; 
    return result; 
} 
  1. Ist das Verhalten dieser Code gut definiert?
  2. Wird es wirklich funktionieren, dass result Variable mit 0 oder -1 geladen wird abhängig von dem Rückgabewert von ?

Für Interesse: Der Code wurde nicht wie das ursprünglich geschrieben - aber ist es, was ich diese unschuldig aussehenden vorstellen Makro ...

ausrollen wird
int foo(int a); // Forward declaration. 

#define BAR() { int a = dosomestuff(); foo(a); } 

int baz() { 
    int result = BAR() ? 0 : -1; 
    return result; 
} 
+0

Yow. Welcher C-Compiler akzeptiert das? gcc tut es sicherlich nicht. – aschepler

+1

@ascheppler: Ironischerweise scheint GCC der * einzige * Compiler zu sein, der es akzeptiert! Siehe Michael Burrs Antwort. –

+0

Der Compiler ist VisualDSP ++ von Analog Devices. Ich werde morgen wahrscheinlich um Unterstützung bitten. –

Antwort

11

Dies ist eine GCC-Erweiterung zu C ‚Anweisung Ausdrücke‘ genannt: http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Das Wichtigste ist, dass eine Aussage Ausdruck das letzte, was gibt es tut, wenn der Wert des Ausdrucks:

Der Die letzte Sache in der zusammengesetzten Anweisung sollte ein Ausdruck sein, gefolgt von einem Semikolon; Der Wert dieses Unterausdrucks dient als der Wert des gesamten Konstrukts.

In Ihrem Beispiel wäre das was auch immer foo(a) zurückgibt.

Der Block muss jedoch in Parens eingeschlossen sein, damit GCC die Syntax akzeptiert.

int foo(); // Forward declaration. 

int baz() { 
    int result = ({ 
     int a = dosomestuff(); 
     foo(a); 
    }) ? 0 : -1; 
    return result; 
} 

Ich bin mir nicht bewusst, dass ein anderer Compiler das unterstützt.

+0

Du bist zuerst da. Als eine FYI hier ist der Link zu allen GCC C-Erweiterungen http://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions –

+4

In diesem speziellen Fall würde wahrscheinlich ein portabler Weg, es zu schreiben geordnet sein. Betrachte 'int result = foo (dosomestuff())? 0: -1; ' –

+1

@ André: definitiv. Der Anwendungsfall für Anweisungsausdrücke scheint darin zu bestehen, "parametersichere" Makros oder Makros zu erstellen, die iterieren. Ich denke, es gibt sehr wenig Grund, sie in normalen Funktionen zu verwenden. –

0

Weil es ein ist Nicht-Pointer einfacher Typ, der genaue Wert wird zurückgegeben und so das Rückgabeverhalten definiert. Dieser Block ist ... wirklich merkwürdig, und ich bin überrascht, dass es einen C-Compiler gibt, der sich da draußen nicht ersticken wird.

1

Ich weiß nicht von einem einzigen Compiler, der das akzeptieren wird. Darüber hinaus wäre es besser für Sie:

int foo(); 
int dosomestuff(); 

int baz() 
{ 
    int result = foo(dosomestuff()) ? 0 : -1; 
    return result; 
} 
4

Sie müssten Ihre Compiler-Dokumentation konsultieren. Dieses Konstrukt ist in Standard C oder Standard C++ nicht erlaubt.

Es ist trivial, dies jedoch z.

int baz() 
{ 
    int result; 
    { 
     int a = dosomestuff(); 
     result = foo(a)? 0: -1; 
    } 
    return result; 
} 
+0

Ja, ich weiß, dass die Funktion viel kürzer gemacht werden kann. Ich gebe nur ein Beispiel für die minimale Änderung, die notwendig ist, um es standardkonform zu machen. Diese Konvertierung ist rein mechanisch, also kann sie auf JEDEM Code verwendet werden, der dieses Konstrukt verwendet. –

1

Es ist nicht Standard C++.

In Standard-C++ schreiben

bool baz() { return !foo(dosomestuff()); } 

Das ist es.

+0

Das ändert das Verhalten - die ursprüngliche Funktion gab "0" oder "-1" zurück, aber bool ist "0" und "+ 1". –

0

Mit C 11 ++ Sie können ziemlich nahe kommen:

int foo(int a); // Forward declaration. 

int baz() { 
    int result = []{ 
     int a = dosomestuff(); 
     return foo(a); 
    }() ? 0 : -1; 
    return result; 
}