2016-03-27 7 views
0

ich diese Aussage jetzt bin mit Wechsel zwischen kleinen und etwas umfangreichere Fehlermeldungen in meinem C Code: C Präprozessormakro #if #else Aussagen ersetzt

#ifdef COMPACTC 
    error_code ((uint16_t) init_cascade, 5); 
#else 
    error_message (__func__, "cascades malloc failed"); 
#endif 

(es ist Teil eines eingebetteten C Code-Bibliothek, so habe ich oft nicht den Speicher zur Verfügung, um die Fehlermeldung Strings zu speichern).

Im ersten Fall (COMPACTC definiert) gebe ich nur eine Funktionsadresse und eine Fehlernummer aus. Im zweiten Fall gebe ich den vollen Funktionsnamen und eine vom Menschen lesbare Fehlermeldung aus.

Da ich diesen Schnipsel kopieren bin über meinen Code jetzt, hoffe ich, dass ich es mit einem einzigen Makro ersetzen kann, was ich so verwenden kann:

error (init_cascade, "cascades malloc failed", 5) 

und bietet den richtigen C Code abhängig davon, ob COMPACTC definiert ist oder nicht.

Vielleicht ist es sogar möglich, die aktuelle Funktion (oder eine eindeutige Kennung) zu haben, automatisch von der aktuellen Position abgeleitet, obwohl ich glaube, der Präprozessor nicht weiß, welche Funktion des Oszilloskops ist es zur Zeit in.

Eine weitere Verbesserung wäre wenn ein eindeutiger Fehlercode (in diesem Fall 5, der auf dem Rückgabewert basiert) automatisch aus der Fehlermeldung generiert werden könnte (wie ein Hashwert oder etwas).

Dann könnte der Makroaufruf, da dies so einfach sein:

error ("cascades malloc failed") 

Natürlich, wenn Hashes verwenden, würde ich eine Art Referenz (Datei/Kommentar) in seine ursprüngliche Nachricht benötigen.

Kontext: Fehlermeldungen auf AVR 8-Bit-MCU

über den Rahmen dieser Frage: Dieser Code wird für den ATmega168 geschrieben (mit nur 2k RAM) und AFAIK gibt es keinen guten/letzten Emulator verfügbar für Linux. Also versuche ich, eine gute Möglichkeit zu finden, Fehlermeldungen/Codes zu erzeugen, ohne dass die Strings all mein Gedächtnis verlieren.

Alternative: C-Funktion?

Eine völlig andere, wahrscheinlich flexiblere Lösung wäre es, eine C-Funktion error (function, message, code) zu definieren und die #if/#else/#endif Konstruktion auf ihren Körper zu verschieben. Ich bin mir nicht sicher, ob ein String-Literal von gcc kompiliert wird, wenn es in einem Funktionsaufruf verwendet wird, aber nie innerhalb des Funktionskörpers verwendet wird.

Edit: Ich habe gerade diese Idee getestet: mit einem String-Literal in einem Anruf, aber nicht im Körper hat es noch zu der ausführbaren Datei von gcc hinzugefügt, so dass diese "Alternative" scheint nicht zu funktionieren.

+1

Für Funktion name können Sie '__FUNCTION__' verwenden und für eine etwas eindeutige ID können Sie '__LINE__' verwenden – Dani

Antwort

2

Dies sollte eigentlich ziemlich einfach sein:

#ifdef COMPACTC 
# define COMBINED_ERROR(function, message, size) error_code((uint16_t)function, size) 
#else 
# define COMBINED_ERROR(function, message, size) error_message (__func__, message) 
#endif 

und jetzt können Sie schreiben:

COMBINED_ERROR(init_cascade, "cascades malloc failed", 5); 
0

Für den ersten Teil schlage ich vor:

#ifdef COMPACTC 
# define error(par1, ...) error_code((uint16_t)par1, __VA_ARGS__) 
#else 
# define error(par1, ...) error_message (__func__, par1, __VA_ARGS__) 
#endif 

Mit dieser Lösung können Sie Definieren Sie so viele Parameter wie Sie möchten.
Für die zweiten Anforderungen in Betracht ziehen, Makro zu verwenden, um spezifischen Code einzufügen. Betrachten Sie das folgende Makro:

#define CallWithError(fnc, ...) { \ 
            int RetCode = fnc(__VA_ARGS__); \ 
            if (RetCode) \ 
             error(init_cascade, "cascades malloc failed", RetCode); \ 
           } 

In diesem Fall können Sie das Makro verwenden, um die Funktion foo anrufen und erzeugen automatisch Fehler:

CallWithError(foo, 1, "hello"); 

in diesem erweitern wird:

{ 
    int RetCode = foo(1, "hello"); 
    if (RetCode) 
     error(init_cascade, "cascades malloc failed", RetCode); 
}