Quali esempi specifici c'è di sapere C farvi un programmatore migliore di alto livello sono?

StackOverflow https://stackoverflow.com/questions/2077913

  •  21-09-2019
  •  | 
  •  

Domanda

Lo so circa l'esistenza di domanda come questo e questo . Mi spiego.

Afet letto l'articolo di Joel Back to Basics e vedere molte domande simili su SO, ho cominciato a chiedersi che cosa sono esempi specifici di situazioni in cui conoscere roba come C può fare un programmatore migliore di alto livello.

Quello che voglio sapere è se ci sono molti esempi di questo. Molte volte, la risposta a questa domanda è qualcosa di simile a " Conoscere C ti dà una migliore sensazione di ciò che sta succedendo sotto le coperte " o " Hai bisogno di una solida base per il vostro programma ", e queste risposte non hanno molto senso. Voglio capire i diversi modi specifici in cui si beneficiare di conoscere i concetti di basso livello,

Joel ha dato un paio di esempi: basi di dati binari vs XML, e stringhe. Ma due esempi in realtà non giustificano l'apprendimento C e / o Assemblea. Quindi la mia domanda è questa: Quali esempi specifici c'è di sapere C che fate un programmatore migliore di alto livello sono

È stato utile?

Soluzione

La mia esperienza con gli studenti di insegnamento e lavorare con persone che hanno studiato solo linguaggi di alto livello è che essi tendono a pensare ad un certo livello di astrazione, e assumono che "tutto viene fornito gratuitamente". Essi possono diventare programmatori molto competenti, ma alla fine hanno a che fare con un codice che ha problemi di prestazioni e quindi si tratta di morderli.

Quando si lavora molto con C, ci pensi l'allocazione di memoria. Spesso pensate layout di memoria (e la cache locale, se questo è un problema). Si capisce come e perché certe operazioni grafiche solo costano molto. Quanto è efficiente o certi comportamenti presa inefficienti sono. Come buffer di lavoro, ecc ritengo che utilizzando le astrazioni in un linguaggio di alto livello quando non so come è implementato sotto le coperte a volte si dà "che salsa extra segreta" quando si parla di prestazioni.

Per esempio, Java ha un garbage collector e non è possibile assegnare direttamente le cose a memoria direttamente. E tuttavia, è possibile effettuare alcune scelte progettuali (ad esempio, con strutture di dati personalizzati) che influiscono sulle prestazioni a causa delle stesse ragioni per cui questo sarebbe un problema in C.

Inoltre, e più in generale, ritengo che sia importante per un programmatore il potere non solo di sapere notazione O-grande (che la maggior parte delle scuole insegnano), ma che in applicazioni reali la costante è anche importante (quali scuole cercano ignorare). La mia esperienza aneddotica è che le persone con competenze in entrambi i livelli linguistici tendono ad avere una migliore comprensione della costante, forse a causa di ciò che ho descritto sopra.

In aggiunta, molti sistemi di livello superiore che ho visto l'interfaccia con le librerie di livello inferiore e le infrastrutture. Per esempio, alcuni di comunicazione, database o librerie grafiche. Alcuni driver per determinati dispositivi, ecc Se sei un programmatore di potere, si può eventially devono avventurarsi là fuori e aiuta ad avere almeno un'idea di ciò che sta accadendo.

Altri suggerimenti

Conoscere roba di basso livello può aiutare molto.

Per diventare un pilota da corsa, devi imparare e capire la fisica di base di come i pneumatici aderenza alla strada. Chiunque può imparare a guidare abbastanza veloce, ma è necessario una buona comprensione delle "basso livello" roba (forze e frizioni, le linee da corsa, acceleratore e freno di controllo bene, ecc) per ottenere quegli ultimi cento delle prestazioni che vi permetterà di vincere la gara.

Ad esempio, se si capisce come l'architettura CPU funziona nel vostro computer, è possibile scrivere codice che funziona meglio con esso (ad esempio, se sai di avere una certa dimensione della cache della CPU o di un certo numero di byte in ogni riga della cache della CPU , è possibile organizzare le vostre strutture di dati e il modo in cui si accede loro di fare il miglior uso della cache - per esempio, l'elaborazione di molti elementi di un array in ordine è spesso più veloce l'elaborazione di elementi casuali, a causa della cache della CPU). Se si dispone di un computer multi-core, poi a comprendere come le tecniche di basso livello come il threading lavoro può ha dato enormi vantaggi (proprio come non capire il livello basso può portare al disastro in filettatura).

Se si capisce come I / O e di caching opere disco I, è possibile modificare le operazioni di file di lavorare bene con esso (ad esempio, se si legge da un file e scrivere ad un altro, lavorando su grandi lotti di dati nella RAM può aiutare a ridurre I / O contesa tra le fasi di lettura e scrittura del codice, e migliorare notevolmente il throughput)

Se si capisce come funzionano le funzioni virtuali, è possibile progettare il codice di alto livello che utilizza le funzioni virtuali e . Se usato in modo errato possono ostacolare gravemente le prestazioni.

Se si capisce come disegno viene gestita, è possibile utilizzare trucchi intelligenti per migliorare la velocità di disegno. per esempio. È possibile disegnare una scacchiera alternativamente disegno 64 caselle bianche e nere. Ma è spesso più veloce di disegnare 32 sqares bianchi e poi 32 quelle nere (perché hai solo per cambiare il colore di disegno due volte invece di 64 volte). Ma in realtà si può disegnare l'intero Consiglio nero, poi XOR 4 strisce su tutta la linea e 4 strisce lungo il bordo in bianco, e questo può essere molto più veloce ancora (2 cambiamenti di colore, e solo 9 rettangoli per disegnare invece di 64). Il pensiero laterale: Questo trucco scacchiera una molto importante abilità di programmazione insegna. Progettando il vostro bene algoritmo, spesso è possibile fare una grande differenza per quanto bene il vostro programma funziona.

La comprensione C, o per quella materia, qualsiasi linguaggio di programmazione a basso livello, ti dà l'opportunità di capire le cose come l'utilizzo della memoria (ad esempio perché è una brutta cosa per creare diversi milioni di oggetti pesanti), come funzionano puntatori / riferimenti a oggetti, ecc.

Il problema è che, come abbiamo creato livelli di astrazione sempre crescente, ci troviamo a fare un sacco di programmazione 'blocco lego', senza capire come i lego in realtà funzionano. E avendo risorse quasi infinite, iniziamo a trattare memoria e risorse come l'acqua, e tendono a risolvere i problemi gettando più ferro la situazione.

Anche se non limitato a C, c'è un enorme beneficio per lavorare ad un livello basso con molto più piccoli sistemi, la memoria vincolata come la vecchia scuola processori a 8 bit Arduino o. Esso ti consente di vivere vicino alla codifica di metallo in un pacchetto molto più accessibile, e dopo aver trascorso il tempo spremitura applicazioni in 512K, vi troverete l'applicazione di queste competenze a un livello più ampio entro la giornata di programmazione al giorno.

Così il linguaggio stesso non è importante, ma avere un più profondo apprezzamento per come tutti i bit si incontrano, e come lavorare in modo efficace a un livello più vicino l'hardware è un insieme di competenze benefici a tutti gli sviluppatori di software.

Per prima cosa, sapendo C aiuta a capire come funziona la memoria nel sistema operativo e in altri linguaggi di alto livello. Quando il vostro C # o Java palloncini programma sul utilizzo della memoria, la comprensione che i riferimenti (che sono fondamentalmente solo puntatori) prendono la memoria troppo, e capire come molte delle strutture di dati sono implementati (che si ottiene dal fare il proprio in C) aiuta a capire che il dizionario sta riservando enormi quantità di memoria che non effettivamente utilizzate.

Per un altro, sapendo C può aiutare a capire come fare uso di livello inferiore è dotata del sistema operativo. Non hai bisogno di questo, spesso, ma a volte potrebbe essere necessario file mappati in memoria, o di utilizzare marshalling in C # e C sarà di grande aiuto a capire quello che stai facendo, quando ciò accade.

Credo che C ha anche aiutato la mia comprensione di protocolli di rete, ma non riesco a mettere il dito su esempi specifici. Stavo leggendo un'altra domanda SO, l'altro giorno in cui qualcuno si lamentava di come bit-field di C sono 'sostanzialmente inutile' e pensavo come elegantemente campi di bit C rappresentano i protocolli di rete di basso livello. Alto livello lingue che si occupano di strutture di bit finiscono sempre un disastro!

In generale, più si conosce, il programmatore meglio sarà.

Tuttavia, a volte conoscere un'altra lingua, ad esempio C, può farti fare la cosa sbagliata, perché ci potrebbe essere un presupposto che non è vero in un linguaggio ad alto livello (come Python o PHP). Ad esempio, si potrebbe supporre che trovare la lunghezza di una lista potrebbe essere O (N) dove N è la lunghezza della lista. Tuttavia, questo non è probabilmente il caso in molti casi linguaggio di alto livello. In Python, per la maggior parte delle cose della lista-come il costo è O (1).

Conoscere altro sulle specifiche di una lingua aiuterà, ma sapendo più in generale potrebbe far fare ipotesi errate.

Proprio "conoscere" C non avrebbe fatto meglio.

Ma, se si capisce il tutto, come nativo binari di lavoro, come fa il lavoro della CPU con essa, quali sono i limiti di architettura, è possibile scrivere un codice che è più facile per CPU.

Per esempio, come le cache L1 / L2 influenzano il vostro lavoro, e come si dovrebbe scrivere il codice per avere più colpi di L1 cache / L2. Quando si lavora con C / C ++ e fare ottimizzazioni pesanti, si dovrà scendere a quel genere di cose.

Non è tanto sapere C come è che il C è più vicino al metallo nudo rispetto a molte altre lingue. È necessario essere più consapevoli di come allocare / deallocare memoria perché devi farlo da soli. Fai da te ti aiuta a capire le implicazioni di molte decisioni che si fanno.

Per me qualsiasi lingua è accettabile fino a quando si capisce come il compilatore / interprete (in pratica) mappa il codice sulla macchina. È un po 'più facile da fare in un linguaggio che espone questa direttamente, ma si dovrebbe essere in grado di, con un po' di lettura, capire come la memoria viene allocata e organizzata, che tipo di schemi di indicizzazione sono più ottimale rispetto ad altri, quali costrutti sono più efficiente per applicazioni particolari, ecc.

Più importante, credo, è una buona comprensione dei sistemi operativi, architetture di memoria, e algoritmi. Se si capisce come funziona l'algoritmo, il motivo per cui sarebbe meglio scegliere un algoritmo o struttura di dati su un altro (ad esempio, HashSet vs List), e come il vostro codice di mappe sulla macchina, non dovrebbe importa quale lingua si sta utilizzando .

Questa è la mia esperienza di come ho imparato e insegnato la programmazione me stesso, in particolare, la comprensione C, questo sta andando di nuovo a primi anni del 1990 quindi potrebbe essere un po 'antico, ma la passione e l'unità è importante:

  • Imparare a comprendere i principi basso livello di computer, come ad esempio la programmazione EGA / VGA, ecco una link all'archivio Simtel sulla guida del programmatore C al PC.
  • La comprensione di come il lavoro di TSR
  • Scarica l'intero archivio di frammenti di Bob Stout che è una grande collezione di codice C che fa una cosa solo -. studiarli e capire, non solo che, la raccolta di frammenti si sforza di essere portatile
  • Sfoglia in codice Concorso Internazionale Obfuscated C ( IOCCC ) on-line, e vedere come il codice C può essere abusato e comprendere i intracies del linguaggio. L'abuso di codice peggiore è il vincitore! Scarica gli archivi e studiarli.
  • Come me, mi è piaciuto il famigerato C Tutorial di Ponzo che mi ha aiutato immensamente, purtroppo, l'archivio è molto difficile da trovare. Se qualcuno sa di dove ottenere loro, si prega di lasciare un commento e io modificare questa risposta per includere il collegamento. V'è un altro che mi ricordo - di Coronado [? Generico] C Tutorial, ancora una volta, la mia memoria su questo è confusa ...
  • Guarda giornale e C utente ufficiale di Dr. Dobb qui - non so se si può ancora farli in stampa ma erano un classico, ricordo la sensazione di tenere una copia stampata in mano e strappare a casa per digitare il codice per vedere cosa succede!
  • Grab un'antica copia di Turbo C v2 che credo si può ottenere da Borland. com e basta giocare con la programmazione a 16 bit C per ottenere una sensazione e la mensa con i puntatori ... sicuro che è antico e vecchio ma a giocare con i puntatori su di esso va bene.
  • capire e imparare puntatori, collegamento qui alla Simtel.net - un collegamento cruciale al raggiungimento di C Guru'ship per mancanza di una parola migliore, anche troverete una miriade di download di pertinenza del linguaggio di programmazione C - mi ricordo che in realtà ordinare l'Archivio Simtel CD e cercando la roba C ...

Un paio di cose che si devono trattare direttamente con in C che altri linguaggi astratto lontano da includere la gestione della memoria esplicita (malloc) e trattare direttamente con i puntatori.

La mia ragazza è un semestre dalla laurea MIT (dove usano prevalentemente Java, Scheme, e Python) con una laurea in Informatica, e sta attualmente lavorando ad una società la cui base di codice è in C ++. Per i primi giorni ha avuto un momento difficile la comprensione di tutti i puntatori / riferimenti / etc.

D'altra parte, ho trovato passando da C ++ a Java molto facile, perché non sono mai stato confuso circa pass-riferimenti per valore vs passaggio per riferimento.

Analogamente, in C / C ++ è molto più evidente che primitive sono solo il compilatore trattare le stesse serie di bit in modi diversi, al contrario di un linguaggio come Python o Ruby dove tutto è un oggetto con proprietà distinte.

Un semplice (non del tutto realistico) esempio per illustrare alcuni dei consigli di cui sopra. Si consideri il apparentemente innocuo

while(true)
   for(Iterator iter = foo.iterator(); iter.hasNext();)
       bar.doSomething( iter.next() )

o il livello ancora più alto

while(true)
    for(Baz b: foo)
        bar.doSomething(b)

Un possibile problema è che ogni volta che gira il mentre ciclo viene creato un nuovo oggetto (l'iteratore). Se tutto ciò che interessa è programmatore di convenienza, allora quest'ultimo è decisamente migliore. Ma se il ciclo deve essere efficiente o la macchina è risorsa vincolata poi si sono praticamente in balia dei progettisti del tuo linguaggio ad alto livello.

Per esempio, una denuncia tipica per fare ad alte prestazioni Java sta avendo arresto dell'esecuzione mentre rifiuti (ad esempio tutti quegli oggetti iteratori allocati) viene recuperato. Non molto buona se il software ha il compito di monitoraggio di missili in arrivo, auto-pilotando un aereo passeggeri, o semplicemente non lasciando all'utente chiedendo perché la GUI ha smesso di rispondere.

Una possibile soluzione (ancora nel linguaggio di più alto livello) sarebbe quello di indebolire la convenienza del iteratore a qualcosa come

Iterator iter = new Iterator();
while(true)
    for(foo.initAlreadyAllocatedIterator(iter); iter.hasNext();)
       bar.doSomething(iter.next())

Ma questo avrebbe senso solo se si ha qualche idea circa l'allocazione della memoria ... altrimenti appena si presenta come un'API brutto. Convenienza costa sempre da qualche parte, e conoscendo roba di livello inferiore può aiutare a identificare e mitigare tali costi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top