Quali principi vengono appresi da C che non possono essere appresi in lingue di livello superiore? [chiuso]


11

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?


2
In ogni caso impari la magia, o parte di essa. Poiché C è "più vicino al metallo", impari di più sul metallo.
Robert Harvey,

1
Non ho mai compreso appieno il concetto di riferimento fino a quando non ho incontrato C ++.
user6245072

6
C ti insegnerà cos'è effettivamente un overflow dello stack. Nel modo più duro.
david25272,

1
Vorrei che i nuovi programmatori iniziassero imparando il buon vecchio Pascal e la programmazione strutturata. Impari ad esprimerti in modo logico e strutturato.
Piegato il

2
Qualcosa che solo C e C ++ ti insegnano è che il compilatore è il tuo peggior nemico.
CodesInChaos,

Risposte:


9

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.


6
Non ho mai capito bene perché la gente menziona sempre la completezza di Turing in questo tipo di discussioni. La completezza di Turing non è significativa in questo contesto; C non è diverso dagli altri linguaggi di programmazione in questo senso, quindi non c'è nulla da imparare sulla completezza di Turing passando a C. L'unica volta in cui la completezza di Turing diventa rilevante è quando si discute di qualcosa che non è completo di Turing, come CSS o HTML . Diamine, se strizza gli occhi abbastanza forte, anche quelli sono Turing-completi . Le domande più significative si concentrano sull'usabilità.
Robert Harvey,

3
@RobertHarvey Il mio punto è che fintanto che una lingua ha un minimo ragionevole di capacità computazionale, il suo "livello" diventa irrilevante dal punto di vista degli algoritmi, che sono le uniche cose che contano in questo contesto.
Greyfade,

3
Perché stai affermando che è del tutto irrilevante per la domanda del PO. I programmatori lo fanno sempre; gettano intorno alla frase "Turing-complete" come se avesse effettivamente un uso significativo in termini pratici. Non importa
Robert Harvey,

2
<irony> La biologia è solo un caso speciale di chimica, che è un caso speciale di fisica delle particelle. Non c'è nulla che puoi imparare dalla biologia se conosci la fisica delle particelle. Giusto? </irony>
Florian F,

3
Vale la pena sottolineare che C richiede semplicemente di rendere esplicite allocazioni e deallocazioni, ma riguardano ancora una macchina astratta, proprio come nei linguaggi di "livello superiore" - la macchina fisica x86 (es.) È ancora fuori dallo scopo di C. Uno può creare una macchina virtuale in modalità sandbox che interpreta il codice C ma non ha alcun controllo sulle allocazioni di memoria della macchina fisica e può comunque essere un'implementazione conforme al 100%.
Theodoros Chatzigiannakis,

13

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.


12
C sta benissimo nel creare astrazioni. È possibile scrivere i metodi in C, ed è possibile confezionare il backup dei dati come strutture nei sistemi operativi in tutta la C. sono stati costruiti utilizzando C. Qual C non è bravo a è soddisfacente idea "moderna" di tutti di quale oggetto-orientamento si suppone a guardare piace.
Robert Harvey,

4
Non proprio. C è un livello leggermente più alto di ASM. Non aspettarti di usare le classi, anche se ci sono modi per farlo , se sei così propenso.
Robert Harvey,

4
Sostituisci "Brainfuck" con "assemblatore" nel tuo commento e dovrebbe essere valido. Ma ciò non significa che userò Brainfuck presto.
Robert Harvey,

6
La tua discussione sulle funzionalità di C ha davvero valore solo se credi che le classi (e la garbage collection, ecc.) Siano un elemento necessario per insegnare a un nuovo programmatore (cosa che io non faccio). Nessuno qui sta sostenendo di provare a usare le lezioni in un linguaggio senza classi.
Robert Harvey,

5
@Robert, la mia tesi è che C è un linguaggio di livello inferiore, e come tale non è certo il miglior linguaggio per comprendere i principi della programmazione, che possiamo anche dire dell'assemblatore, e, solo perché sono linguaggi di livello inferiore non significa sono in qualche modo più vicini ai "veri" principi di programmazione. Queste lingue sono invece migliori per capire come funzionano l'hardware e i sistemi operativi e, se questo è l'interesse, raccomando di saltare direttamente al livello più basso, nell'apprendimento dell'architettura dell'insieme di istruzioni e del linguaggio macchina. Altrimenti, ci sono molte lingue tra cui scegliere.
Erik Eidt,

8

C e la macchina (astratta)

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.)

Come si fa a imparare? E come si impara?

Okay, in realtà imparare l'hardware implica cose diverse da C. Ma C può insegnare qualcos'altro ai programmatori oggi?

Penso che dipenda.

  • Ci sono alcuni che direbbero che puoi imparare meglio un concetto lavorando in un ambiente che lo offre e lo incoraggia, spesso in più modi.
  • Ci sono alcuni che direbbero che puoi imparare meglio un concetto lavorando in un ambiente che non lo offre e dove invece devi costruirlo tu stesso.

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.

Esclusivamente in C

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.


5

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.


Sono completamente d'accordo. C ti insegnerà molto su come funzionano le cose, il che aiuta molto a capire a) perché sono state scritte lingue di livello superiore (ad es. Cosa intendevano astrarre), e b) come funzionano quelle lingue di livello superiore dietro le quinte, che sicuramente una buona conoscenza da avere. Non insegnerà i principi e potrebbe non essere così semplice, ma ne conseguirai un rispetto per esso, i computer e una comprensione più profonda delle lingue di livello superiore di conseguenza. Leggi anche Back to Basic di Joel Spolsky: joelonsoftware.com/articles/fog0000000319.html
jleach

1
La tua risposta sicuramente va bene, ma se scrivi 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 ;-)
Doc Brown,

Non sono sicuro, ma mi fiderei del compilatore Java per ottimizzarlo via :-)
Bruno Schäpper,

Anche il programmatore Java esperto sa immediatamente dove si trova il problema e probabilmente eviterà di scrivere questo codice in primo luogo. Questo problema specifico è discusso in tutorial Java elementari. Quindi questo certamente non è qualcosa che può essere appreso da C ma non da Java.
Peter Taylor,

@PeterTaylor Se hai un istruttore Java che conosce la sua C, sì. Ma dubito che questo tipo di conoscenza rimarrà intorno una volta che le persone che conoscono C sono morte. Per il programmatore C, è la definizione stessa di cosa sia una stringa C, che dice loro che il mio esempio di codice non può essere efficiente. Per il programmatore Java, è una conoscenza profonda, arcana e poco utilizzata sulle astrazioni che usano, che dice loro di evitare questo tipo di codice. Ok, sto esagerando un po 'qui, ma hai l'idea: il programmatore C deve saperlo, il programmatore Java potrebbe cavarsela senza saperlo.
cmaster - ripristina monica il

2

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.


1
C è una lingua molto buona da imparare prima di imparare quelle "cose ​​di livello superiore che pensi che C non supporti", perché ti aiuta a capire come funzionano effettivamente quelle cose (e quanto costano).
Brendan,

@Brendan: non sono sicuro che l'intento del tuo commento sia quello di esprimere un accordo, un disaccordo o solo un sidenote alla mia risposta.
Doc Brown,

I programmi C scritti da professionisti vengono rilasciati con sovraccarichi del buffer e arresti anomali. Quindi, mentre un programmatore disciplinato può scegliere di imparare queste cose , la C la lingua non insegna intrinsecamente semplicemente essendo impoverita. Esistono molti modi sbagliati (e peggio ancora, mescolando più modi incoerenti) per fare la gestione degli errori senza eccezioni e creare una struttura senza oggetti, ad esempio.
Erik Eidt,

@ErikEidt: davvero, ma specialmente nell'ecosfera C esistono molti libri, tutorial e altro materiale che tratteranno questi argomenti. Ad esempio, "Writing Solid Code" di Steve Maguire. Naturalmente, se qualcuno sceglie la prima edizione di K&R per l'apprendimento della sintassi della lingua, probabilmente non diventerà un programmatore migliore.
Doc Brown,

1

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.


1
Quindi, cosa può insegnarti C che le lingue di livello superiore non possono?
Philip Kendall,

2
Penso che la risposta implicita sia: " Niente , almeno non le cose che i sostenitori di solito sostengono". Ecco come capisco la risposta comunque.
Jörg W Mittag,

-3

È 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?

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.