2012-11-05 7 views
6

Sto scrivendo codice C incorporato per un microcontrollore. Il codice deve essere condiviso tra tre diverse schede di circuito e le configurazioni di input/output sono impostate in fase di esecuzione da alcune tabelle durante l'inizializzazione.Come si verifica una funzione C per l'input valido durante la compilazione?

Il microcontrollore ha 24 canali ADC e ho una funzione che può impostare o cancellare un pin come canale ADC. Ciò significa che un input per la funzione può essere composto da 0 a 23 (che è impostato nella tabella) e nient'altro.

Vorrei mettere una sorta di "cosa" del preprocessore o del compilatore che potrebbe identificare che la funzione ha ricevuto un valore diverso da 0-23 e lanciare qualche tipo di errore o avvertimento e impedire la compilazione del codice nel caso in cui qualcuno inserisca un valore non valido nella tabella.

Qualcuno ha qualche consiglio su come meglio farlo?

+1

È potrebbe usare asserzioni statiche. – imreal

+1

Penso che tu stia confondendo le cose qui. Una funzione riceve input durante il runtime e il preprocessore o il compilatore può controllare solo cose note durante la compilazione. È necessario aggiungere un controllo all'inizio della funzione che verificherà i limiti di input. – SomeWittyUsername

+0

Il motivo per cui ho pensato che ci fosse un modo per controllarlo durante la compilazione è che non ci saranno mai dei valori passati a quella funzione che non sono già noti al momento della compilazione. – Adam

risposta

3

Sulla maggior parte dei compilatori (preprocessori) è possibile utilizzare la direttiva #error.

I.e.

#define ADC_CHANNEL 34 
#if ADC_CHANNEL > 23 
#error ADC_CHANNEL exceeds maximum allowed value 
#endif 

Quanto sopra genererebbe un errore e non verrebbe compilato.

Quindi utilizzare ADC_CHANNEL come input per la propria funzione.

Oppure si può fare un ADC_CHANNELenum, e definire ADC_CHANNEL_0 = 0, ADC_CHANNEL_1 = 1 ... ADC_CHANNEL_23 = 23. Quindi fai in modo che la tua funzione prenda il tipo ADC_CHANNEL_t, o qualsiasi altra cosa tu voglia chiamare, e in questo modo se la funzione viene chiamata usando il tipo enumerato come argomento, non ci sarà modo di usare un valore fuori limite.

Esempio:

typedef enum {ADC_CHANNEL_0 = 0, 
       ADC_CHANNEL_1 = 1, 
       ADC_CHANNEL_2 = 2, 
       // ...etc... 
       ADC_CHANNEL_22 = 22, 
       ADC_CHANNEL_23 = 23} adc_channel_t; 

void setClearAdcPin(adc_channel_t adcChannel) { 
    // ...function body... 
} 

(Non è tecnicamente necessario il = 0, = 1, ecc, in quanto il compilatore dedurre che dall'ordine Per default enum s partono da 0 e l'incremento di 1 per. ogni valore. Ma la definizione di ogni valore manualmente è più sicuro, e permette di fare le cose come includere solo 3 possibili canali di ADC che si potrebbe forse usare, anche se non sono consecutivi.)

+1

Sfortunatamente, il numero intero standard verrà accettato anche se la funzione attende un enum: http://liveworkspace.org/code/69da85aa7cfefb69d7d6f23b940f7462 – SomeWittyUsername

+0

Vero, non verrà generato un errore del compilatore. Immagino di voler dire che se si chiarisce che la funzione deve essere chiamata con il tipo enumerato, allora si spera che qualcuno abbia meno probabilità di rovinarlo. Ma non bisogna sottovalutare la capacità delle persone di rovinare tutto. – llakais

+0

Usa alcune opzioni del compilatore per fare in modo che il controllo del tipo dia un errore. –

1

è possibile controllare la gamma in compilatore (al contrario del preprocessore) per questo trucco sporco:

const char PIN = 23; 
struct check_23 { 
    unsigned long bits: PIN+9; 
}; 

questo non compilerà se PIN> 23

Quindi, al fine di garantire la vostra funzione è data solo a tempo di compilazione costanti come argomenti si fornisce una macro invece di una funzione:

#define CONCAT(a, b) a##b 
#define MAKESTRUCTNAME(a,b) CONCAT(a,b) 

#define PinFunction(PinArg)\ 
struct MAKESTRUCTNAME(PinCheckStruct, __LINE__) {\ 
    unsigned long bits: (PinArg)+9;\ 
};\ 
RealPinFunction(PinArg);\ 
+0

Com'è collegato alla chiamata di funzione? – SomeWittyUsername

+0

@icepack, si antepone ogni chiamata di funzione con esso. (Non ho avuto il tempo di scrivere tutto allora) –

+0

Nizza. Dovrai inoltre negare all'utente l'interfaccia della funzione reale per prevenire gli abusi. A parte questo sembra un tentativo eroico di emulare alcune delle funzionalità del modello C++ :) – SomeWittyUsername

Problemi correlati