Domanda

Sto lavorando su un progetto su un 8051 dove ogni byte conta.Come tale, sto utilizzando alcune variabili globali in cui normalmente non avrebbe.Il metodo normale di passaggio di puntatori in una funzione aggiunge troppa testa qui.

Ho un certo numero di funzioni che uso singolo bit variabili (un compilatore estensione specifica per C) per segnalare l'esito di una funzione in aggiunta al normale valore di ritorno.

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;

}

Dato che la tecnica è male, c'è qualche modo per rendere il codice più chiaro?

Come meglio posso indicare che le chiamate di funzione avrà l'effetto di impostazione di queste bandiere?Sono commenti abbastanza?Dovrei nome le funzioni di indicare le loro API (quasi-ungherese-stile)?Devo usare una macro per contrassegnare tali chiamate:

#define FUNCTION_SETS_FLAGS(code) (code)

FUNCTION_SETS_FLAGS( c = A_Function() );

Altre idee?

È stato utile?

Soluzione

I tuoi globali sono etichettati per chiarezza, che è un buon inizio.

Idealmente si desidera qualcosa che non verrà compilato se si sbaglia. Ciò significa che le macro e commenti non funzioneranno.

mi piacerebbe restare ad una convenzione di denominazione per le funzioni - non necessariamente ungheresi, ma qualcosa come A_Function_Returns_Flags, o meno prolissa, se si può pensare che

.

Altri suggerimenti

Utilizzando una convenzione, se si desidera chiamare "ungherese" o no, è il modo migliore che posso pensare per celebrare questo estemporaneo. Stilisticamente, una sorta di denominazione prefisso sarebbe preferibile sopra la # define vuota, almeno per me.

Questo è in realtà abbastanza comune, credo. So che l'ambiente di programmazione S60 utilizza un sacco di tag convenzionali sulle funzioni per indicare che essi generano eccezioni, per esempio.

Ho fatto il mio dottorato di ricerca su un problema analogo in Java. Vi posso dire l'unica cosa che non si deve fare: non fare affidamento sulla documentazione perché poi si dipende da qualcuno effettivamente leggerlo. È necessario aggiungere qualche suggerimento in nome del metodo per indicare che l'utente dovrebbe leggere la documentazione per conoscere gli effetti collaterali. Se si sceglie qualcosa e sono coerenti con esso, probabilmente stare più possibilità.

Se si desidera solo per dire che una funzione influisce variabile globale (s), allora un semplice (ungherese) prefisso potrebbe aiutare.

Ma se si vuole parlare di ogni singolo bandiera (s) che colpisce, poi, utilizzando la funzione di intestazione è probabilmente la strada da percorrere. Come per esempio,

  /*************************************************************************
     * 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> 
  *************************************************************************/

Questo non davvero aiutare, ma GCC è un modo per fare il di fronte di ciò che si desidera:per contrassegnare le funzioni no gli effetti collaterali.Vedere la const e pure attributi.Questo è più per l'ottimizzazione di documentazione, di pensiero:se il compilatore sa che una determinata funzione non esaminare i dati di altri argomenti, è in grado di eseguire più intelligente ottimizzazioni come loop-invariante codice di movimento.

Si potrebbe utilizzare una macro per simulare la funzione di avere più parametri:


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++;
}

Non ho provato a compilare, quindi non posso dire che questo lavoro, ma penso che dovrebbe.

Per prima cosa vorrei provare a codificare in un modo che non ci sono solo un produttore e un solo consumatore per ognuna di queste bandiere. Poi vorrei cancellare / impostare un flag solo quando necessario. Per quanto riguarda l'indicazione l'effetto collaterale, un colpo di testa di serie sulla parte superiore della funzione, lo stile doxygen, dovrebbe essere sufficiente:

    // 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;
    }

D'altra parte, se l'errore e ready bandiere sono mutuamente esclusivi, è possibile utilizzare un byte (o bit all'interno di un byte / register) per indicare prontezza o uno stato di errore.

0 per un errore, per 1 senza errori e 2 non pronto / pronto / senza errori (o -1, 0, 1, a prescindere)

IIRC, lo standard 8051 set di istruzioni non opera sui singoli bit, in modo da utilizzare un intero byte (vari) flag non si dovrebbe dare un enorme calo di prestazioni.

Se non si è già fatto, si potrebbe anche voler controllare la sdcc progetto su sourceforge , è un compilatore C specificamente pensato per essere utilizzato per lo sviluppo embedded che si rivolge anche il 8051, oltre il compilatore supporta una serie di personalizzato, intrinseci compilatore e non standard specifici target per vari casi di utilizzo, anche personalmente ho trovato lo sviluppo squadra di essere molto aperto e reattivo al di idee per nuovi miglioramenti e altre richieste funzionalità correlata.

Se avete davvero attaccare con queste variabili globali, si può rendere evidente che una funzione li può modificare da aspettarsi riferimenti a loro come argomenti delle funzioni:

unsigned char A_Function (bit *p_error_flag, bit *p_data_ready_flag)
{
  ...
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top