Credo che C sia un buon linguaggio per apprendere i principi alla base della programmazione. Che cosa impari nelle lingue di livello inferiore che vengono "ingannate" da quelle di alto livello, come Ruby?
Credo che C sia un buon linguaggio per apprendere i principi alla base della programmazione. Che cosa impari nelle lingue di livello inferiore che vengono "ingannate" da quelle di alto livello, come Ruby?
Risposte:
Non ci sono principi, nel senso astratto generale dell'informatica, che sono presenti in C che non sono presenti anche in linguaggi di livello superiore. Tutta l'informatica si riduce agli algoritmi e tutti gli algoritmi possono essere implementati in qualsiasi linguaggio completo di Turing come lo è C.
La differenza che C separa dai linguaggi di livello superiore è simile alla differenza che il codice macchina trasporta a parte C: La relazione della macchina con il codice.
Mentre scrivi il codice in lingue di alto livello, non ti preoccupi (in generale) di come il tuo codice interagisce con la macchina. La macchina virtuale che il linguaggio definisce per sé nasconde molti di quegli aspetti dell'esecuzione del codice.
In C, l'interazione del tuo programma con la memoria è in primo piano. È molto più che dover gestire l'uso dell'heap, include l'interazione del codice con lo stack e in che modo il semplice accesso alla memoria del codice influisce sul comportamento e sulle prestazioni del codice, nemmeno sull'ordine degli accessi alla memoria può sfuggire alla tua attenzione, poiché la lettura della memoria sbagliata al momento sbagliato può compromettere efficacemente le prestazioni.
Nelle lingue di livello superiore, queste cose semplicemente non sono così ovvie. La memoria viene allocata e deallocata a tua insaputa, e talvolta senza il tuo suggerimento. Molto spesso, questo è semplicemente fuori dal tuo controllo. Il quando, dove, come e perché della maggior parte delle allocazioni di memoria sono semplicemente nascosti da te.
Allo stesso modo, nella direzione opposta, la scrittura del codice macchina o del codice assembly porta in primo piano ancora più dettagli: quasi nulla è lasciato al di fuori del tuo ambito di competenza e il tuo codice deve essere scritto consapevole di ogni allocazione, ogni risorsa, ogni pezzo di dati che passa attraverso i registri della CPU - conoscenza così lontana dai linguaggi di alto livello da essere arcana.
So che C è un buon linguaggio per apprendere i principi alla base della programmazione.
Non sono d'accordo. In C mancano troppe funzioni per apprendere i principi alla base della programmazione. Le caratteristiche di C per la creazione di astrazioni sono terribili e l'astrazione è uno dei principi chiave alla base della programmazione.
Se vuoi imparare come funziona l'hardware, e quindi un po 'di simpatia meccanica per la macchina, dovresti imparare il codice della macchina, ovvero l'architettura del set di istruzioni, e studiare anche la costruzione della cache delle CPU moderne. Si noti che non sto raccomandando il linguaggio assembly, basta capire le istruzioni hardware, in modo da capire cosa genera un compilatore.
Se vuoi imparare i principi di programmazione, usa un linguaggio moderno come Java, C # o Swift o una delle dozzine di altri come Rust. Inoltre, studia i diversi tipi di paradigmi di programmazione, incluso quello funzionale.
La maggior parte dei linguaggi di programmazione sono descritti in termini di macchine astratte. Quindi, vengono implementati utilizzando set di strumenti come compilatori, linker, assemblatori, interpreti, analizzatori statici, linguaggi intermedi e hardware che produrranno collettivamente un risultato che onora almeno tutto il comportamento previsto della macchina astratta, come osservato da un programma .
C non fa eccezione alla regola sopra. È descritto in termini di una macchina astratta che non ha idea del tuo hardware reale.
In quanto tale, quando le persone dicono che C ti insegna come funziona realmente il tuo computer, ciò che di solito significa che C ti insegna come funziona C. Ma essendo C così pervasivo nella programmazione dei sistemi, è comprensibile che molte persone inizino a confonderlo con il computer stesso. E personalmente vorrei arrivare al punto di dire che sapere come funziona la C è spesso più importante che sapere come funziona il computer stesso.
Tuttavia, C e il computer sono cose diverse. L'hardware reale è in realtà complicato - in modi che rendono le specifiche C leggere come un libro per bambini. Se sei interessato a come funziona il tuo hardware, puoi sempre cercare un manuale e iniziare a scrivere codice in un assemblatore. Oppure puoi sempre iniziare a conoscere i circuiti digitali in modo da poter progettare un po 'di hardware da solo. (Per lo meno, apprezzerai quanto è alto il livello C.)
Okay, in realtà imparare l'hardware implica cose diverse da C. Ma C può insegnare qualcos'altro ai programmatori oggi?
Penso che dipenda.
Non essere troppo veloce per scegliere una di queste possibilità. Scrivo codice da molti anni e non ho ancora idea di quale sia la risposta corretta, o se la risposta corretta sia solo una delle due, o se esiste una risposta corretta su questo problema.
Sono un po 'propenso a credere che alla fine dovresti probabilmente applicare entrambe le opzioni, vagamente nell'ordine in cui le ho descritte. Ma non penso che sia davvero una questione tecnica, penso che sia principalmente educativa. Ogni persona sembra imparare in modi significativamente diversi.
Se hai risposto alla domanda di cui sopra coinvolgendo almeno la seconda opzione che ho proposto, allora hai già alcune risposte sotto controllo: tutto ciò che può essere appreso in lingue di livello superiore può essere appreso meglio reinventandolo in C o in meno espanso aggiungendo C al mix.
Ma, indipendentemente dalla tua risposta, ci sono certamente alcune cose che puoi imparare quasi esclusivamente da C (e forse una manciata di altre lingue).
C è storicamente importante. È una pietra miliare che puoi guardare e apprezzare da dove veniamo e forse ottenere un po 'più contesto su dove stiamo andando. Puoi capire perché esistono alcune limitazioni e puoi apprezzare che alcune limitazioni sono state eliminate.
C può insegnarti a lavorare in ambienti non sicuri. In altre parole, può allenarti a guardarti le spalle quando la lingua (qualsiasi lingua) non può o non lo farà per te, per qualsiasi motivo. Questo può renderti un programmatore migliore anche in ambienti sicuri perché produrrai meno bug da solo e perché sarai in grado di disattivare temporaneamente la sicurezza per ridurre la velocità extra del tuo programma altrimenti sicuro (ad esempio l'uso di puntatori in C #), nei casi in cui la sicurezza comporta un costo di runtime.
C può insegnarti che ogni oggetto ha requisiti di archiviazione, un layout di memoria, il fatto che è possibile accedere alla memoria attraverso uno spazio di indirizzi limitato e così via. Mentre altre lingue non richiedono la tua attenzione su questi argomenti, ci sono alcuni casi in cui alcune intuizioni acquisite possono aiutarti a prendere decisioni più informate.
C può insegnarti i dettagli del collegamento e dei file oggetto e altre complessità attraverso il suo sistema di compilazione. Questo può darti un'utile comprensione pratica di come un programma compilato in modo nativo passa spesso dal codice sorgente all'esecuzione.
C può piegare la mente a pensare in modi nuovi attraverso il concetto di comportamento indefinito. Il comportamento indefinito è uno dei miei concetti preferiti nello sviluppo del software, perché lo studio delle sue implicazioni sui compilatori non classici è un esercizio mentale unico che non puoi assolutamente ottenere da altre lingue. Tuttavia, dovrai rifiutare prove ed errori e iniziare a studiare la lingua in modo attento e deliberato prima di poter apprezzare appieno questo aspetto.
Ma forse la realizzazione più importante che C può garantirti, essendo un linguaggio di piccole dimensioni, è l'idea che tutta la programmazione si riduce a dati e operazioni . Potresti considerare le cose come classi modulari con gerarchie e interfacce con invio virtuale o eleganti valori immutabili che vengono gestiti utilizzando funzioni matematiche pure. E va tutto bene, ma C ti ricorderà che sono solo dati + operazioni . È una mentalità utile perché ti permette di abbattere alcune barriere mentali.
Il motivo per cui C è buono per l'apprendimento non è che insegna alcun principio . Ti insegna come funzionano le cose .
La C può essere paragonata a una di quelle belle vecchie macchine degli anni '70 o '80, che sono state appena costruite per guidare. Puoi separarli, avvitare per vite e capire come funziona ogni parte e come funziona insieme alle altre parti che puoi prendere in mano per guardarle. Una volta comprese tutte le parti, si ha un'immagine molto chiara di come tutto funziona.
Le lingue moderne sono più simili a un'auto moderna in cui il motore è fondamentalmente una scatola nera, troppo complesso per essere compreso dal proprietario medio dell'auto. Quelle macchine possono fare molto, diamine, in questi giorni stanno imparando attivamente a guidare da sole. E con quella complessità e comfort, l'interfaccia utente è stata spostata molto più lontano da ciò che sta realmente accadendo nel motore.
Quando apprendi la programmazione in C, entri in contatto con molte delle viti e dei dadi di cui è composto un computer. Ciò consente di sviluppare una comprensione della macchina stessa. Ad esempio, ti permette di capire perché non è una buona idea costruire una lunga stringa come questa:
java.lang.String result = "";
for(int i = 0; i < components.size; i++) {
result = result + components[i];
};
(Spero che questo sia Java corretto, non lo uso da un po 'di tempo ...) Da questo esempio di codice, non è ovvio il motivo per cui il ciclo abbia una complessità quadratica. Ma è così, ed è la ragione per cui questo codice si fermerà quando avrai qualche milione di piccoli componenti da concatenare. Il programmatore C esperto sa immediatamente dove si trova il problema e probabilmente eviterà di scrivere tale codice in primo luogo.
for(int i = 0; i < strlen(s); i++)
in C, il ciclo avrà anche una complessità quadratica, ed è altrettanto invisibile come nel tuo esempio Java ;-)
Esistono linguaggi migliori di C per apprendere "i principi alla base della programmazione", in particolare i principi teorici, ma C può essere utile per imparare alcune cose pratiche e importanti sull'artigianato. La risposta di greyfade è sicuramente corretta, ma IMHO c'è molto di più che puoi imparare da C di come gestire la memoria da solo. Per esempio,
come creare programmi con una completa gestione degli errori in assenza di eccezioni
come creare una struttura in un programma senza avere alcun supporto linguistico per l'orientamento agli oggetti
come gestire i dati in assenza di strutture di dati come elenchi dinamici, dizionari o un'astrazione di stringhe utile
come evitare errori comuni come overflow dell'array anche quando il compilatore o l'ambiente di runtime non ti avvisano automaticamente
come creare soluzioni generiche senza supporto linguistico per modelli o generici
e ho già detto che puoi imparare a gestire la memoria da solo, ovviamente? ;-)
Inoltre, imparando C, imparerai da dove provengono i punti in comune sintattici di C ++, Java, C #, Obiettivo C.
Nel 2005, Joel Spolsky scrisse una raccomandazione per l'apprendimento del C prima di qualsiasi altra lingua di livello superiore. I suoi argomenti sono
"non sarai mai in grado di creare codice efficiente in lingue di livello superiore."
"Non sarai mai in grado di lavorare su compilatori e sistemi operativi, che sono alcuni dei migliori lavori di programmazione in circolazione."
"Non ti fiderai mai di creare architetture per progetti su larga scala"
"se non riesci a spiegare perché ti while(*s++ = *t++);
copia una stringa, o se questa non è la cosa più naturale del mondo per te, beh, stai programmando in base alla superstizione
Certo, ciò che ha scritto è sicuramente discutibile, ma molti dei suoi argomenti di IMHO sono ancora validi oggi.
Le due astrazioni di base dell'informatica sono le macchine di Turing e il calcolo di Lambda, e C è un modo per sperimentare la visione del calcolo della macchina di Turing: principalmente una successione di azioni di basso livello da cui emerge un risultato desiderabile. Ma devi tenere presente che C viene fornito con il suo modello di calcolo. Quindi, l'apprendimento del C ti insegnerà i dettagli di basso livello della macchina astratta C, che sta diventando molto diversa dalle architetture reali. Una delle prime cose che mi è stato insegnato in C era di non cercare mai di superare in astuzia il compilatore applicando trucchi "intelligenti", e sembra che la tendenza sia verso sempre più ottimizzazioni nei compilatori. Come in altri linguaggi di alto livello, quando scrivi in C, i compilatori in qualche modo capiscono cosa ti aspetti di fare sulla macchina C astratta e lo fanno accadere sull'hardware reale,
Quindi, ciò che intendo è che l'apprendimento del C non ti fornirà necessariamente una buona idea di ciò che accade effettivamente nell'hardware. "C è vicino alla macchina" dovrebbe essere inteso come "più vicino della maggior parte delle lingue di livello superiore". Imparare direttamente l'architettura del software sarà più gratificante se vuoi un quadro più accurato di "come funziona".
D'altro canto, l'apprendimento del C può familiarizzare con la programmazione del sistema, i tipi di basso livello, i puntatori e in particolare l'allocazione della memoria. Per quanto riguarda gli algoritmi di apprendimento e la struttura dei dati, non c'è alcun vantaggio nell'apprenderli in C piuttosto che in altre lingue.
È una domanda a risposta molto aperta, che potrebbe non dare una risposta definitiva. Puoi imparare praticamente tutto in ogni lingua purché tu capisca gli interni del framework linguistico. C ti obbliga a comprendere i dettagli inferiori perché è stato progettato principalmente per scrivere un sistema operativo. Anche dopo tanti anni, è ancora una delle lingue più utilizzate principalmente grazie a sistemi embedded e progetti open source. Quindi, la domanda è: cosa vuoi imparare? E in quale dominio?