Cosa dovrebbe sapere un programmatore C? [chiuso]


11

Quali sono alcuni concetti / tecniche / caratteristiche del linguaggio che ogni programmatore C decente dovrebbe conoscere / essere a conoscenza (esclude l'ingegneria del software generale e simili e si concentra solo su cose specifiche del C). Vorrei sapere in modo da poter colmare alcune possibili lacune nella mia conoscenza del C.


9
Inizia con le domande C di Stack Overflow e vedi se c'è qualcosa che non conosci.
Chrisaycock,

3
Il programmatore AC dovrebbe probabilmente saperlo2 + 2 = 4
Edward Strange,

21
Dovrebbero conoscere un negozio che vende scarpe a prova di proiettile.
Adam Crossland,

1
Ci sono centinaia di libri scritti su questo argomento. La tua domanda è davvero abbastanza vaga. Dovrai essere più specifico per ottenere risposte decenti che non sono solo un elenco di cose. E vedendo le risposte incantate così lontano da questa domanda, penso che debba essere rielaborato o chiuso.
Walter,

2
Un altro linguaggio di programmazione?
Muhammad Alkarouri,

Risposte:


19

Specifico per C? A parte costrutti standard comuni alla maggior parte dei linguaggi procedurali, dovrei dire:

  • (ab) utilizzando il preprocessore
  • linker vs compilatore
  • Puntatori Puntatori Puntatori!
  • Come gli array sono puntatori sono array
  • Come funzionano le stringhe C e come sono anche puntatori e matrici
  • Il cattivo utilizzo della stringa C può causare overflow del buffer
  • Come trasmettere qualsiasi cosa a qualsiasi cosa (è tutto solo 1s e 0s dopo tutto :))
  • Gestione manuale della memoria malloc / free
  • Stack vs Heap
  • Puntatore aliasing, (perché è illegale in C99)
  • Pensando allo sviluppo in termini di moduli (file .h / .c) con una serie di funzioni esposte pubblicamente anziché rigorosamente classi
  • sindacati
  • Perché sprintf può farti saltare il piede
  • Puntatori a funzione

Aggiungerei "buffer overflow" all'elenco.
Aidan Cully,

@Aidan, buona cattura. Aggiunto.
Doug T.,

2
In che modo gli array e i puntatori C non sono gli stessi: books.google.ca/…
Matthieu,

i puntatori avrebbero dovuto essere ripetuti almeno 3 volte di più
Gaurav,

8

Comprendi i puntatori e capirai i computer.


12
No, avrai semplicemente l'illusione di capire i computer.
Lavoro

4

Oltre all'ottima risposta di pitagra,

come scrivere (o almeno leggere) dichiarazioni complicate, come char (*(*funcs[4])())[10]

funcs è una matrice [4] di puntatori a una funzione che restituisce il puntatore alla matrice [10] di char


1
Se diventa così complesso, forse questo appartiene a un commento?
Lavoro

7
forse dovrebbe imparare a evitare di scrivere così?
FabianB,

3
  1. Regole di promozione intere
  2. Inizializza tutto su un valore noto
  3. GOTO non è male soprattutto se usato per gestire eccezioni / fallimenti
  4. malloc e / o calloc possono restituire NULL ... assicurati che i tuoi valori di ritorno di controllo
  5. Frequenti allocazioni di memoria di piccole dimensioni possono causare la frammentazione dell'heap.
  6. Puntatore aritmetico
  7. Le maschere bit sono il tuo amico
  8. x >> 1 equivale a x / 2 per numeri interi senza segno

+1 per GOTO non essere cattivo :)
zvrba,

2

Il programmatore AC dovrebbe conoscere ... altre lingue! ;-) È sempre fruttuoso conoscere concetti di altri linguaggi di vari paradigmi, come OOP, programmazione funzionale e così via.

Più seriamente, uno sguardo al contest di programmazione offuscata è divertente e, curiosamente, anche una bella esperienza.


2

Ho citato "buffer overflow" in un commento alla risposta di Pythagras, probabilmente dovrei chiarire cosa volevo dire un po '. In C, non è sufficiente sapere che lavorare direttamente con la memoria è pericoloso - dovresti anche capire i modi precisi in cui è pericoloso. Non mi piace molto la metafora di "spararti al piede" per tutti questi casi - il più delle volte, non sei tu a premere il grilletto, ma spesso è un attore con interessi contrari al tuo e / o ai tuoi utenti .

Ad esempio, in un'architettura con uno stack discendente (le architetture più popolari si adattano a questo conto - x86 e ARM generalmente inclusi), quando si chiama una funzione, l'indirizzo di ritorno per la funzione verrà inserito nello stack dopo le variabili locali definite nella corpo della funzione. Quindi se dichiarate un buffer come variabile locale ed esponete quella variabile al mondo esterno senza controllare l'overflow del buffer, in questo modo:

void myFn(void) {
    char buf[256];
    gets(buf);
}

un utente esterno può inviarti una stringa che sovrascrive l'indirizzo di ritorno dallo stack - in pratica, può cambiare l'idea di runtime del programma del grafico di chiamata che porta alla funzione corrente. Quindi l'utente ti dà una stringa che è la rappresentazione binaria di un codice eseguibile per la tua architettura, una quantità sufficiente di riempimento da cui traboccare lo stack myFne alcuni dati aggiuntivi per sovrascrivere l'indirizzo di ritorno per myFnpuntare al codice che ti ha dato. Se ciò accade, allora quando . Dovresti capire perché un overflow del buffer rispetto allo stack è spesso (ma non sempre) più facilmente sfruttabile rispetto a uno contro l'heap, e dovresti capire come è disposta la memoria nell'heap (non in modo troppo dettagliato, necessariamente, ma il idea che amyFn normalmente avrebbe restituito il controllo al chiamante, si diramerà invece al codice fornito dall'utente malintenzionato. Se si scrive codice C (o C ++) che potrebbe essere esposto a utenti non attendibili, è necessario comprendere questo vettore di attaccomalloc()La regione ha strutture di controllo che la circondano possono aiutare a capire perché il tuo programma si blocca in un altro malloc()o dentrofree() ).

C ti espone a dettagli di basso livello su come funziona la tua macchina e ti dà un controllo più diretto sulla tua macchina rispetto a qualsiasi altra lingua modificata dall'utente in uso diffuso oggi. Con una grande potenza derivano grandi responsabilità: in realtà è necessario comprendere quei dettagli di basso livello per lavorare con C in modo sicuro ed efficace.


0

Oltre alle altre buone risposte, vorrei aggiungere all'elenco tecniche di programmazione difensiva .

Ad esempio utilizzando assert all'inizio / alla fine delle funzioni per verificare il contratto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.