Frage

Ich arbeite an einem Projekt auf einem 8051 wo jedes Byte zählt. Als solche verwende ich einige globale Variablen, wo ich normalerweise nicht würde. Das normale Verfahren von hier fügt zu viel Overhead-Zeiger in eine Funktion übergeben.

Ich habe eine Reihe von Funktionen, die Einzel-Bit-Variablen (a Compiler spezifische Erweiterung C ) zu signalisieren, das Ergebnis einer Funktion, zusätzlich zu dem normalen Rückgabewert verwenden.

bit global_error_flag = 0;
bit global_data_ready_flag = 0;

unsigned char A_Function (void) {
    // Do some stuff

    if ( badness ) {
        global_error_flag = 0;
        global_data_ready_flag = 1;

        return 0;
    }

    if ( data_is_ready_use ) {
        global_data_ready_flag = 1;
    }

    return a_value;    
}

void Other_Function (void) {
    unsigned char c;

    c = A_Function();

    if( global_error_flag) {
        // Do error stuff here.
    }
    else
    if( global_data_ready_flag ) {
        // Do data processing here.
    }
    global_error_flag = 0;
    global_data_ready_flag = 0;

}

Da die Technik böse ist, ist es eine Möglichkeit, kann ich den Code klarer machen?

Wie am besten sollte ich angeben, welche Anrufe funktionieren die Nebenwirkung der Einstellung dieser Flags haben? Sind Kommentare genug? Soll ich die Funktionen nennen ihre API (quasi-ungarisch-Stil), um anzuzeigen? Soll ich einen Makro verwenden, solche Anrufe markieren:

#define FUNCTION_SETS_FLAGS(code) (code)

FUNCTION_SETS_FLAGS( c = A_Function() );

Jede andere Ideen?

War es hilfreich?

Lösung

Ihre Globals sind zur besseren Übersicht markiert, das ist ein guter Anfang.

Im Idealfall möchten Sie etwas, das nicht kompiliert werden, wenn Sie es falsch ist. Das bedeutet, Makros und Kommentare werden nicht funktionieren.

ich auf eine Namenskonvention für die Funktionen bleiben würde - nicht unbedingt ungarisch, aber so etwas wie A_Function_Returns_Flags oder weniger ausführlich, wenn Sie daran denken können

.

Andere Tipps

eine Konvention verwenden, ob Sie es „ungarische“ nennen wollen oder nicht, ist der beste Weg, ich denke, kann diese ohne Weiteres zu markieren. Stilistisch wäre besser, über den leeren #define eine Art Präfix zu benennen, zumindest für mich.

Das ist eigentlich ziemlich üblich ist, glaube ich. Ich weiß, dass die S60-Programmierumgebung viele herkömmliche Tags auf Funktionen verwendet, um anzuzeigen, dass sie Ausnahmen auslösen, zum Beispiel.

habe ich meine Ph.D. auf einem ähnlichen Problem in Java. Ich kann Ihnen das eine Sache sagen Sie nicht tun sollten: nicht auf die Dokumentation verlassen, weil dann hängen Sie auf jemand tatsächlich zu lesen. Sie benötigen einen Hinweis in dem Methodennamen hinzufügen, um anzuzeigen, dass der Benutzer die Dokumente lesen sollte über Nebenwirkungen zu lernen. Wenn Sie etwas und stehen im Einklang mit ihm holen, stehen Sie wahrscheinlich die Chance.

Wenn Sie nur erwähnen wollen, dass eine Funktion globale Variablen beeinflusst (s), dann ein einfacher (ungarisch) Präfix helfen könnte.

Aber wenn man jedes einzelne Flagge erwähnen möchte (n), dass es wirkt, dann die Funktion Headers ist wahrscheinlich der Weg zu gehen. Wie zum Beispiel:

  /*************************************************************************
     * FUNCTION    : <function_name>
     * DESCRIPTION : <function description> 
     * PARAMETERS  : 
     *  Param1  - <Parameter-1 explanation>
     *  Param2  - <Parameter-2 explanation>
     *  Param3  - <Parameter-3 explanation>
     * RETURN      : <Return value and type>
     * GLOBAL VARIABLES USED: 
     *  Global1 - <Global-1 explanation>
     *  Global2 - <Global-2 explanation>
     *  Global3 - <Global-3 explanation> 
  *************************************************************************/

Dies ist wirklich nicht helfen, aber GCC hat eine Möglichkeit, die Gegenteil zu tun von dem, was Sie wollen: Funktionen zu markieren, welche haben keine Nebenwirkungen. Siehe const und pure Attribute. Das ist mehr für die Optimierung als Dokumentation, dachte: wenn der Compiler weiß, dass eine gegebene Funktion untersucht keine anderen Daten als ihre Argumente, kann es klügere Optimierungen durchführt wie schlaufen unveränderlicher Code .

Sie können einen Makro verwenden, um die Funktion zu simulieren mehr Parameter haben:


unsigned char _a_function(void);

#define A_Function(ret_val) (*(ret_val) = _a_function(), !global_error_flag)

...
unsigned char var;
/* call the function */
if (!A_Function(&var))
{
    /* error! */
}
else
{
    /* use var */
    var++;
}

Ich habe nicht versucht, es zu kompilieren, so kann nicht sagen, dass dies funktionieren wird, aber ich denke, es sollte.

Zuerst würde ich versuchen, es in einer Weise zu codieren, dass es nur einen Hersteller und nur ein Verbraucher für jede dieser Fahnen. Dann würde ich klar / set nur eine Flagge, wenn nötig. Wie bei den Nebeneffekt angibt, ein Standard-Header auf der Funktion, doxygen Stil, sollte genug sein:

    // Function func
    // Does something
    // Consumes ready_flag and  sets error_flag on error.

    int func()
    {
        if (ready_flag)
        {
            //do something then clear the flag
            if (some_error)
                error_flag = x;
            ready_flag = 0;
        }
        //don't mess with the flags outside of their 'scope'
        return 0;
    }

Auf der anderen Seite, wenn die Fehler und bereit Fahnen gegenseitig ausschließen, können Sie ein Byte (oder Bits in einem Byte / Register) Bereitschaft oder einen Fehlerzustand anzuzeigen.

0 für einen Fehler, 1 für nicht-ready / fehlerfrei und 2 für ready / fehlerfrei (oder -1, 0, 1, was auch immer)

IIRC, der Standard-8051-Befehlssatz arbeitet nicht auf einzelne Bits, also ein ganzes Byte für (verschiedene) Fahnen verwenden, sollten Ihnen eine großen Leistungseinbußen nicht geben.

Wenn Sie nicht bereits getan haben, wollen Sie vielleicht auch die sdcc Projekt auf Source , es ist ein C-Compiler ist speziell für Embedded-Entwicklung wird dafür gedacht, die auch die 8051 Ziele, zusätzlich der Compiler eine Reihe von benutzerdefinierten, zielspezifische und nicht-Standard-Compiler-Spezifika für verschiedene Anwendungsfälle unterstützt, auch finde ich persönlich habe die Entwicklung Team als sehr offen und ansprechbar über Ideen für neue Erweiterungen und andere zugehörige Feature-Requests.

Wenn Sie wirklich mit dieser globalen Variablen zu halten haben, können Sie es auf der Hand, dass eine Funktion sie ändern können durch Verweise auf sie als Funktionsargumente erwarten:

unsigned char A_Function (bit *p_error_flag, bit *p_data_ready_flag)
{
  ...
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top