2013-07-08 14 views
7

Ho letto la scritta sul muro, Evita Globali. Il che porta alla domanda ovvia, come è meglio farlo?Come non usare le variabili globali in c

Ovviamente voglio farlo con un progetto attuale. L'obiettivo è quello di consentire a un PC remoto di inviare "sequenze di tasti" alle applicazioni che dispongono già di un lettore stdin. L'idea è di lasciare che il codice esistente rilevi che non vi è alcuna sequenza di tasti in sospeso, quindi controlla se c'è un "tasto di udp" e, in caso affermativo, inseriscilo in modo che appaia come input da tastiera. Minimamente invasivo e non richiede l'uso di retinature nel codice di altre persone.

Così ho acciottolata un piccolo lettore di socket UDP che utilizza una funzione setup() per aprire e legare la porta, poi una funzione service() in un ciclo che utilizza un bloccante select() una volta, nessun ciclo, basta controllare se c'è qualcosa da leggere al momento. Se è così, leggere i dati dalla presa e fare qualcosa con esso, altrimenti restituire un 0.

// pseudo c 
char c; 

setup(); 
while (1) 
{ 
    c = check_for_keyboard_entry(); 
    if (c == 0) 
     c = service(); 
    handle_keypress(c); 
    do_a_bunch_of_other_stuff(); 
} 

Il modo più ovvio per farlo è con un paio di variabili globali per il trasferimento al porto, timeout, di sockaddr ecc tra il due funzioni. Ma tu sei un appassionato di mondo, giusto?

Quindi qual è il modo preferito per trasferire le sei o otto vars tra le funzioni?

Se dovessi utilizzare vars statici nello setup(), sarebbero accessibili dalla routine service()?

Suppongo che una struttura che viene malloc-ed e girata funzionerebbe. Dovrei avere un cleanup() per chiudere il socket e liberare la memoria.

RICORDO, QUESTA È UNA DOMANDA. NO C++!

+2

_'' Suppongo che una struttura che viene malloc-ed e girata funzionerebbe_ '' - Hai capito! –

+0

+1 per velocità raw! Qualche altro approccio? –

+1

Correggere \ 0 a 0 o '\ 0' –

risposta

3

È possibile inserire tutte queste informazioni in un struct. La struttura può essere visibile al client o un tipo opaco. Un tipo opaco può essere una scelta migliore in modo da poter nascondere i dati (incapsulamento) per tipi complessi.

typedef struct { 
port_t port; 
timeout_t timeout; 
sockaddr_t sockaddr; 
etc_t etc; 
} my_stuff; 

poi passarlo in giro per riferimento:

void Foo(my_stuff*); 

suppongo una struct che ottiene malloc-ed e passato in giro avrebbe funzionato. Dovrei avere un cleanup() per chiudere il socket e liberare la memoria.

In genere, una struct non dovrebbe sempre essere malloc 'ed. Ma sì, questo potrebbe essere il caso in cui è richiesto.

+0

Ma questo non rende la struttura globale? O intendevi avere 'foo()' restituire un puntatore a 'my_stuff'? In tal caso, come potrebbe persistere 'my_stuff' quando viene chiuso l'ambito' foo() '? O faresti lo statico 'my_stuff' in' foo() '? –

+2

@WesMiller: puoi metterlo in pila nello scope esterno. Quindi 'int main() {roba mia_stuff; stuff.port = 80; ...; Foo (e roba); ...; ritorno 0; } '. Le variabili statiche nelle funzioni sono di fatto globali e condividono problemi simili. –

+0

@MaciejPiechotka +1. Applicato uno schiaffo di droga ben meritato e auto-somministrato. La risposta è così ovvia una volta che la vedi. –