2010-09-22 12 views
6

Sono abbastanza comodo codificare in linguaggi come Java e C#, ma ho bisogno di usare C per un progetto (a causa di chiamate API OS di basso livello) e ho qualche difficoltà a gestire i puntatori e gestione della memoria (come visto here)Apprendimento C proveniente da lingue OO gestite

In questo momento sto praticamente digitando il codice e alimentandolo al compilatore per vedere se funziona. Questo non mi sembra giusto. Qualcuno può indicarmi delle buone risorse per farmi capire i puntatori e la gestione della memoria, provenienti dalle lingue gestite?

+5

Quando lavoravo a C - che era molti anni fa, il mio riferimento preferito per C - Kernighan Ritchie - http://www.amazon.com/gp/product/images/0131103628/ref=dp_image_0?ie=UTF8&n = 283155 & s = libri – InSane

+1

Benvenuti nel mondo del fantastico. Preparati per prestazioni e flessibilità senza precedenti! –

+0

Sono sulla stessa barca, tranne sostituire Java e C# con Python e C++. L'ho risolto rivedendo il codice che abbiamo in sovversione e rivisitando la sezione sui puntatori e sui cast dei miei libri C++ mentre aspetto che arrivi la mia copia del "linguaggio di programmazione C di Richie". – xnine

risposta

3

Una delle buone risorse che hai trovato già, quindi.

Ovviamente si sta compilando con tutti gli avvisi, no?

L'apprendimento in base alla qualità dipende in gran parte dalla qualità del compilatore e dagli avvisi/errori che fornisce. Il meglio in questo senso che ho trovato nel mondo linux/POSIX è clang. Traccia bene l'origine degli errori e ti informa abbastanza bene dei file di intestazione mancanti.

+0

++ Per "compilare con tutti gli avvisi su". – AlcubierreDrive

1

Alcuni consigli:

  • By varibles di default vengono memorizzati nello stack.
  • Varianti immessi nelle funzioni per Valore
  • Attenersi allo stesso processo per allocare e liberare memoria. es allocare e libera nella stessa funzione
  • equivalente C di

    Integer i = new Integer(); 
    
    i=5; 
    

è

int *p; 

p=malloc(sizeof(int)); 

*p=5; 
  • allocazione di memoria (malloc) può fallire, in modo da controllare il puntatore per nullo prima di usarlo.
  • Le funzioni del sistema operativo possono guastarsi e questo può essere rilevato dai valori di ritorno.
1

Impara a utilizzare gdb per scorrere il codice e stampare i valori delle variabili (compila con -g per abilitare i simboli di debug).

Utilizzare valgrind per verificare la presenza di perdite di memoria e altri problemi correlati (come il danneggiamento dell'heap).

1

Il linguaggio C non esegue nulla che non gli si dice esplicitamente di fare.

Non ci sono distruttori chiamati automaticamente per te, che sono sia buoni che cattivi (dal momento che i bug nei distruttori possono essere un problema).

Un modo semplice per ottenere un comportamento di distruttore un po 'automatico consiste nell'utilizzare l'ambito per costruire e distruggere le cose. Questo può diventare brutto dal momento che gli ambiti annidati spostano le cose più lontano e più a destra.

if (var = malloc(SIZE)) { // try to keep this line 
    use_var(var); 
    free(var); // and this line close and with easy to comprehend code between them 
} else { 
    error_action(); 
} 
return; // try to limit the number of return statements so that you can ensure resources 
     // are freed for all code paths 

Cercando di rendere il vostro look codice come questo per quanto possibile aiuterà, anche se non è sempre possibile.

Creare una serie di macro o funzioni in linea per inizializzare gli oggetti è una buona idea. Crea anche un'altra serie di funzioni che assegnano la memoria degli oggetti e la passano alle funzioni di inizializzazione. Ciò consente di inizializzare facilmente sia oggetti locali che allocati dinamicamente. Anche operazioni simili per funzioni simili a quelle di un distruttore sono una buona idea.

Utilizzare le tecniche OO è una buona pratica in molti casi, e farlo in C richiede solo un po 'più di digitazione (ma consente un maggiore controllo). Putter, getter e altre funzioni di supporto possono aiutare a mantenere gli oggetti in stati coerenti e ridurre le modifiche che devi apportare quando trovi un errore, se riesci a mantenere l'interfaccia uguale.

Si dovrebbe anche esaminare la funzione perror e la "variabile" errno "variabl".

Di solito si vuole evitare di usare qualsiasi cosa come le eccezioni in C. In genere cerco di evitarli anche in C++, e li uso solo per errori veramente brutti - quelli che non dovrebbero accadere. Uno dei motivi principali per evitarli è che non ci sono chiamate distruttive create magicamente in C, quindi GOTO non locali spesso perderanno (o rovineranno in altro modo) qualche tipo di risorsa. Detto questo, ci sono cose in C che forniscono una funzionalità simile.

Il meccanismo di eccezione principale simile a C sono le funzioni setjmp e longjmp. setjmp viene chiamato da una posizione nel codice e ha passato una variabile (opaca) (jmp_buf) che può essere successivamente passata a longjmp. Quando viene effettuata una chiamata a longjmp, in realtà non ritorna al chiamante, ma ritorna come precedentemente chiamato setjmp con quel jmp_buf. setjmp restituirà un valore specificato dalla chiamata a longjmp. Chiamate regolari a setjmp return 0.

Un'altra eccezione come la funzionalità è più specifica della piattaforma, ma include segnali (che hanno i propri trucchi).

Altre cose da guardare in sono:

Il assert macro, che può essere usato per causare l'uscita del programma quando il parametro (un test logico di qualche tipo) non riesce. Le chiamate a assert vanno via quando si #define NDEBUG prima di #include <assert.h>, quindi dopo aver provato è possibile rimuovere facilmente le asserzioni. Questo è veramente buono per testare i puntatori NULL prima di dereferenziarli, così come molte altre condizioni. Se una condizione non riesce, assert tenta di stampare il nome del file di origine e il numero di riga del test non riuscito.

La funzione abort causa l'uscita del programma in caso di errore senza eseguire tutte le operazioni di pulizia eseguite da exit. Questo può essere fatto con un segnale su alcune piattaforme. assert chiamate abort.

Problemi correlati