Quels sont les principes tirés de C qui ne peuvent pas être appris dans les langages de niveau supérieur? [fermé]


11

Je crois que C est un bon langage pour apprendre les principes de la programmation. Que pensez-vous apprendre dans des langues de niveau inférieur qui sont «magiques» loin de celles de haut niveau, comme le rubis?


2
Vous apprenez la magie, ou une partie, de toute façon. Parce que C est "plus proche du métal", vous en apprendrez plus sur le métal.
Robert Harvey

1
Je n'ai jamais complètement compris le concept de référence jusqu'à ce que je rencontre le C ++.
user6245072

6
C vous apprendra ce qu'est réellement un débordement de pile. À la dure.
david25272

1
Je souhaite que les nouveaux programmeurs commencent par apprendre un bon vieux Pascal et une programmation structurée. Vous apprenez à vous exprimer de façon logique et structurée.
Bent

2
Quelque chose que seuls C et C ++ vous apprennent, c'est que le compilateur est votre pire ennemi.
CodesInChaos

Réponses:


9

Il n'y a pas de principes, dans le sens abstrait général de l'informatique, qui sont présents en C qui ne sont pas également présents dans les langages de niveau supérieur. Toute l'informatique se résume à des algorithmes, et tous les algorithmes peuvent être implémentés dans n'importe quel langage qui est Turing-complet comme C l'est.

La différence entre C et les langages de niveau supérieur est similaire à la différence entre le code machine et C: la relation de la machine avec le code.

Lorsque vous écrivez du code dans des langages de haut niveau, vous ne vous préoccupez pas (généralement) de la façon dont votre code interagit avec la machine. La machine virtuelle que le langage définit pour lui-même cache bon nombre de ces aspects de l'exécution du code.

En C, l'interaction de votre programme avec la mémoire est maintenue au premier plan. C'est plus que simplement que vous devez gérer votre utilisation du tas, cela inclut l'interaction de votre code avec la pile et la façon dont le simple accès à la mémoire de votre code affecte le comportement et les performances de votre code - pas même l'ordre d'accès à la mémoire peut échapper à votre attention, car la lecture de la mauvaise mémoire au mauvais moment peut paralyser efficacement les performances.

Dans les langues de niveau supérieur, ces choses ne sont tout simplement pas aussi évidentes. La mémoire est allouée et désallouée à votre insu et parfois sans votre demande. Le plus souvent, cela est tout simplement hors de votre contrôle. Le moment, où, comment et pourquoi de la plupart des allocations de mémoire vous sont simplement cachés.

De même, dans l'autre sens, l'écriture de code machine ou de code d'assemblage apporte encore plus de détails au premier plan: presque rien n'est laissé en dehors de votre domaine de compétence, et votre code doit être écrit en tenant compte de chaque allocation, chaque ressource, chaque élément de données qui passe à travers les registres du CPU - connaissances si éloignées des langages de haut niveau qu'elles sont obscures.


6
Je n'ai jamais tout à fait compris pourquoi les gens mentionnent toujours l'intégralité de Turing dans ce genre de discussions. La complétude de Turing n'a pas de sens dans ce contexte; Le C n'est pas différent des autres langages de programmation à cet égard, donc il n'y a rien à apprendre sur Turing-compléteness en passant à C. Le seul moment où Turing-completeness devient pertinent est quand on discute de quelque chose qui n'est pas Turing-complete, comme CSS ou HTML . Enfer, si vous plissez les yeux assez fort, même ceux-ci sont complets de Turing . Les questions les plus significatives portent sur la convivialité.
Robert Harvey

3
@RobertHarvey Mon point est que tant qu'un langage a un minimum raisonnable de capacité de calcul, son "niveau" devient non pertinent du point de vue des algorithmes, qui sont les seules choses qui comptent dans ce contexte.
greyfade

3
Parce que vous soulevez un point qui n'a rien à voir avec la question du PO. Les programmeurs font cela tout le temps; ils lancent l'expression «Turing-complete» comme si elle avait en fait une utilité significative en termes pratiques. Ce n'est pas le cas, sauf pour souligner que cela n'a pas d'importance.
Robert Harvey

2
<irony> La biologie n'est qu'un cas particulier de la chimie, qui est un cas particulier de la physique des particules. Il n'y a rien que vous puissiez apprendre de la biologie si vous connaissez la physique des particules. </irony>
Florian F

3
Il convient de souligner que C vous oblige simplement à rendre explicites les allocations et les désallocations, mais elles concernent toujours une machine abstraite, tout comme dans les langages de "niveau supérieur" - la machine physique (par exemple) x86 est toujours hors de portée de C. One peut créer une machine virtuelle parfaitement sandboxée qui interprète le code C mais n'a aucun contrôle sur les allocations de mémoire de la machine physique et il peut toujours s'agir d'une implémentation conforme à 100%.
Theodoros Chatzigiannakis

13

Je sais que C est un bon langage pour apprendre les principes de la programmation.

Je ne suis pas d'accord. C manque trop de fonctionnalités pour apprendre les principes de la programmation. Les fonctionnalités de C pour créer des abstractions sont terribles, et l'abstraction est l'un des principes clés de la programmation.

Si vous voulez apprendre comment fonctionne le matériel, et donc une certaine sympathie mécanique pour la machine, vous devez apprendre le code machine, alias l'architecture du jeu d'instructions, et également étudier la construction du cache des processeurs modernes. Notez que je ne recommande pas le langage d'assemblage, comprenez simplement les instructions matérielles, donc vous comprenez ce que génère un compilateur.

Si vous voulez apprendre les principes de programmation, utilisez un langage moderne comme Java, C # ou Swift, ou l'une des dizaines d'autres comme Rust. Etudiez également les différents types de paradigmes de programmation, notamment fonctionnels.


12
C est très bien pour créer des abstractions. Vous pouvez écrire des méthodes en C, et vous pouvez empaqueter des données sous forme de structures en C. Des systèmes d'exploitation entiers ont été construits en utilisant C. Ce que C n'est pas bon satisfait l'idée «moderne» de chacun de ce que l'orientation d'objet est censée ressembler comme.
Robert Harvey

4
Pas assez. C est un niveau un peu plus élevé que ASM. Ne vous attendez pas à y utiliser des classes, bien qu'il existe des moyens de le faire , si vous êtes si enclin.
Robert Harvey

4
Remplacez «Brainfuck» par «assembleur» dans votre commentaire, et cela devrait toujours être vrai. Mais cela ne signifie pas que je vais bientôt utiliser Brainfuck.
Robert Harvey

6
Votre argument sur les fonctionnalités de C n'a vraiment de mérite que si vous pensez que les classes (et le ramasse-miettes, etc.) sont un élément nécessaire pour enseigner à un nouveau programmeur (ce que je n'ai pas). Personne ici ne préconise d'essayer d'utiliser des classes dans un langage sans classe.
Robert Harvey

5
@Robert, mon argument est que C est un langage de niveau inférieur, et en tant que tel, ce n'est pas le meilleur langage pour comprendre les principes de programmation, ce que nous pouvons également dire à propos de l'assembleur, et ce n'est pas parce que ce sont des langages de niveau inférieur ils sont en quelque sorte plus proches des "vrais" principes de programmation. Ces langages permettent plutôt de mieux comprendre le fonctionnement du matériel et des systèmes d'exploitation, et si tel est l'intérêt, je recommande de passer directement au niveau le plus bas, dans l'apprentissage de l'architecture des jeux d'instructions et du langage machine. Sinon, il y a beaucoup de langues à choisir.
Erik Eidt

8

C et la machine (abstraite)

La plupart des langages de programmation sont décrits en termes de machines abstraites. Ensuite, ils sont implémentés à l'aide d'ensembles d'outils tels que des compilateurs, des éditeurs de liens, des assembleurs, des interprètes, des analyseurs statiques, des langages intermédiaires et du matériel qui produiront collectivement un résultat qui honore au moins tout le comportement attendu de la machine abstraite, tel qu'observé par un programme .

C ne fait pas exception à la règle ci-dessus. Il est décrit en termes d'une machine abstraite qui n'a aucune notion de votre matériel réel.

En tant que tel, lorsque les gens disent que C vous apprend comment fonctionne réellement votre ordinateur, ils veulent généralement dire que C vous apprend comment C fonctionne. Mais C étant si omniprésent dans la programmation des systèmes, il est compréhensible que beaucoup de gens commencent à le confondre avec l'ordinateur lui-même. Et j'irais personnellement jusqu'à dire que savoir comment fonctionne C est souvent plus important que de savoir comment fonctionne l'ordinateur lui-même.

Mais encore, C et l'ordinateur sont des choses différentes. Le matériel réel est en fait compliqué - d'une manière qui fait lire la spécification C comme un livre pour enfants. Si vous êtes intéressé par le fonctionnement de votre matériel, vous pouvez toujours rechercher un manuel et commencer à écrire du code dans un assembleur. Ou vous pouvez toujours commencer à vous renseigner sur les circuits numériques afin de pouvoir concevoir vous-même du matériel. (À tout le moins, vous apprécierez le niveau élevé de C.)

Comment n'apprenez - vous? Et comment apprenez- vous ?

D'accord, l'apprentissage du matériel implique autre chose que C. Mais C peut-il enseigner autre chose aux programmeurs aujourd'hui?

Je pense que cela dépend.

  • Il y en a qui diraient que l'on peut mieux apprendre un concept en travaillant dans un environnement qui le propose et l'encourage, souvent de multiples façons.
  • Certains diront que vous pouvez mieux apprendre un concept en travaillant dans un environnement qui ne le propose pas et où vous devez plutôt le construire vous-même.

Ne soyez pas trop rapide pour choisir l'une de ces possibilités. J'écris du code depuis de nombreuses années et je n'ai toujours aucune idée de laquelle est la bonne réponse, ou si la bonne réponse est juste l'une des deux, ou s'il existe une telle chose comme une bonne réponse sur cette question.

Je suis légèrement enclin à croire que vous devriez probablement éventuellement appliquer les deux options, dans l'ordre dans lequel je les ai décrites. Mais je ne pense pas que ce soit vraiment une question technique, je pense que c'est principalement une question éducative. Chaque personne semble apprendre de différentes manières.

Exclusivement en C

Si vous avez répondu à la question ci-dessus en impliquant au moins la deuxième option que j'ai proposée, alors vous avez déjà quelques réponses à votre actif: tout ce qui peut être appris dans des langues de niveau supérieur peut être mieux appris en le réinventant en C ou à moins étendu en ajoutant C au mélange.

Mais, quelle que soit votre réponse, il y a certainement quelques choses que vous pouvez apprendre presque exclusivement à partir de C (et peut-être d'une poignée d'autres langues).

  • C est historiquement important. C'est une étape importante que vous pouvez regarder et apprécier d'où nous venons et peut-être obtenir un peu plus de contexte sur notre chemin. Vous pouvez comprendre pourquoi certaines limitations existent et vous pouvez apprécier que certaines limitations ont été levées.

  • C peut vous apprendre à travailler dans des environnements dangereux. En d'autres termes, il peut vous entraîner à surveiller vos arrières lorsque la langue (n'importe quelle langue) ne peut pas ou ne veut pas le faire pour vous, pour quelque raison que ce soit. Cela peut faire de vous un meilleur programmeur même dans des environnements sûrs, car vous produirez moins de bogues par vous-même et parce que vous pourrez désactiver temporairement la sécurité afin de réduire la vitesse de votre programme autrement sûr (par exemple, l'utilisation de pointeurs en C #), dans les cas où la sécurité a un coût d'exécution.

  • C peut vous apprendre que chaque objet a des exigences de stockage, une disposition de mémoire, le fait que la mémoire est accessible via un espace d'adressage fini, etc. Bien que d'autres langues n'aient pas besoin de votre attention sur ces questions, il existe quelques cas où une certaine intuition acquise peut vous aider à prendre des décisions plus éclairées.

  • C peut vous renseigner sur les détails des fichiers de liens et d'objets et d'autres subtilités grâce à son système de construction. Cela peut vous donner une compréhension pratique sur la façon dont un programme compilé en mode natif passe souvent du code source à l'exécution.

  • C peut inciter votre esprit à penser de nouvelles façons grâce au concept de comportement indéfini. Le comportement indéfini est l'un de mes concepts préférés dans le développement de logiciels, car l'étude de ses implications sur les compilateurs non classiques est un exercice mental unique que vous ne pouvez pas vraiment obtenir à partir d'autres langages. Cependant, vous devrez rejeter les essais et erreurs et commencer à étudier la langue de manière prudente et délibérée avant de pouvoir pleinement apprécier cet aspect.

  • Mais la réalisation la plus importante que C peut vous accorder, étant un petit langage, est peut-être l'idée que toute la programmation se résume aux données et aux opérations . Vous voudrez peut-être considérer les choses comme des classes modulaires avec des hiérarchies et des interfaces avec une répartition virtuelle, ou des valeurs immuables élégantes qui sont exploitées à l'aide de fonctions mathématiques pures. Et c'est très bien - mais C vous rappellera que ce ne sont que des données et des opérations . C'est un état d'esprit utile car il vous permet de faire tomber pas mal de barrières mentales.


5

La raison pour laquelle C est bon pour l'apprentissage n'est pas qu'il enseigne des principes . Il vous apprend comment les choses fonctionnent .

C peut être comparé à l'une de ces bonnes vieilles voitures des années 70 ou 80, qui ont été conçues pour conduire. Vous pouvez les déchirer, vis par vis, et comprendre comment chaque pièce fonctionne, et comment elle fonctionne avec les autres pièces que vous pouvez prendre entre vos mains pour regarder. Une fois que vous avez compris toutes les parties, vous avez une idée très claire du fonctionnement de l'ensemble.

Les langues modernes ressemblent plus à une voiture moderne où le moteur est essentiellement une boîte noire, beaucoup trop complexe pour être compris par le propriétaire de voiture moyen. Ces voitures peuvent faire beaucoup, diable, ces jours-ci, elles apprennent activement à conduire seules. Et avec cette complexité et ce confort, l'interface utilisateur a été beaucoup plus éloignée de ce qui se passe réellement dans le moteur.

Lorsque vous apprenez à programmer en C, vous entrez en contact avec beaucoup de vis et d'écrous dont est fait un ordinateur. Cela vous permet de développer une compréhension de la machine elle-même. Par exemple, cela vous permet de comprendre pourquoi ce n'est pas une bonne idée de construire une longue chaîne comme celle-ci:

java.lang.String result = "";
for(int i = 0; i < components.size; i++) {
     result = result + components[i];
};

(J'espère que c'est du Java correct, je ne l'ai pas utilisé depuis un moment ...) D'après cet exemple de code, il n'est pas évident pourquoi la boucle a une complexité quadratique. Mais c'est le cas, et c'est la raison pour laquelle ce code s'arrêtera brutalement lorsque vous aurez quelques millions de petits composants à concaténer. Le programmeur C expérimenté sait instantanément où est le problème et évitera probablement d'écrire un tel code en premier lieu.


Je suis complètement d'accord. C vous apprendra beaucoup sur la façon dont les choses fonctionnent, ce qui permet de comprendre a) pourquoi les langues de niveau supérieur ont été écrites (par exemple, ce qu'elles signifiaient pour l'abstraction), et b) comment ces langues de niveau supérieur fonctionnent en arrière-plan, ce qui à coup sûr de bonnes connaissances à avoir. Il n'enseignera pas les principes et ne sera peut-être pas aussi facile, mais vous en ressortirez avec un respect pour lui, des ordinateurs et une meilleure compréhension des langues de niveau supérieur. Lisez aussi Retour à la base par Joel Spolsky: joelonsoftware.com/articles/fog0000000319.html
jleach

1
Votre réponse est sûrement correcte, mais si vous écrivez for(int i = 0; i < strlen(s); i++)en C, la boucle aura également une complexité quadratique, et elle est tout aussi évidente que dans votre exemple Java ;-)
Doc Brown

Pas sûr, mais je ferais confiance au compilateur Java pour optimiser cela :-)
Bruno Schäpper

Le programmeur Java expérimenté sait également instantanément où est le problème et évitera probablement d'écrire un tel code en premier lieu. Ce problème spécifique est abordé dans les didacticiels Java élémentaires. Ce n'est donc certainement pas quelque chose qui peut être appris de C mais pas de Java.
Peter Taylor

@PeterTaylor Si vous avez un instructeur Java qui connaît son C, oui. Mais je doute que ce type de connaissances se maintienne une fois que les personnes qui connaissent C sont mortes. Pour le programmeur C, c'est la définition même de ce qu'est une chaîne C, qui leur dit que mon exemple de code ne peut pas être efficace. Pour le programmeur Java, ce sont des connaissances profondes, obscures et peu utilisées sur les abstractions qu'ils utilisent, qui leur disent d'éviter ce type de code. Ok, j'exagère un peu ici, mais vous avez l'idée: le programmeur C doit le savoir, le programmeur Java peut s'en tirer sans le savoir.
cmaster - réintègre monica

2

Il existe de meilleurs langages que C pour apprendre "les principes de la programmation", en particulier les principes théoriques, mais C peut être bon pour apprendre des choses pratiques et importantes sur le travail artisanal. La réponse de Greyfade est certainement correcte, mais à mon humble avis, vous pouvez apprendre plus de C que la gestion de la mémoire par vous-même. Par exemple,

  • comment créer des programmes avec une gestion complète des erreurs en l'absence d'exceptions

  • comment créer une structure dans un programme sans avoir de support de langage pour l'orientation d'objet

  • comment gérer les données en l'absence de structures de données comme des listes dynamiques de taille importante, des dictionnaires ou une abstraction de chaîne utile

  • comment éviter les erreurs courantes comme les débordements de tableaux, même lorsque le compilateur ou l'environnement d'exécution ne vous avertit pas automatiquement

  • comment créer des solutions génériques sans prise en charge linguistique des modèles ou des génériques

  • et ai-je mentionné que vous pouvez apprendre à gérer la mémoire par vous-même, bien sûr? ;-)

De plus, en apprenant le C, vous apprendrez d'où viennent les points communs syntaxiques du C ++, Java, C #, Objective C.

En 2005, Joel Spolsky a écrit une recommandation pour apprendre le C avant tout autre langage de niveau supérieur. Ses arguments sont

  • "vous ne pourrez jamais créer de code efficace dans des langages de niveau supérieur."

  • "Vous ne serez jamais en mesure de travailler sur des compilateurs et des systèmes d'exploitation, qui sont parmi les meilleurs travaux de programmation du moment."

  • "On ne vous fera jamais confiance pour créer des architectures pour des projets à grande échelle"

  • "si vous ne pouvez pas expliquer pourquoi while(*s++ = *t++);copie une chaîne, ou si ce n'est pas la chose la plus naturelle au monde pour vous, eh bien, vous programmez en fonction de la superstition

Bien sûr, ce qu'il a écrit est sûrement discutable, mais à mon humble avis, beaucoup de ses arguments sont toujours valables aujourd'hui.


1
C est un très bon langage à apprendre avant d'apprendre ces «choses de niveau supérieur que vous pensez que C ne prend pas en charge», car il vous aide à comprendre comment ces choses fonctionnent réellement (et à quel point elles sont chères).
Brendan

@Brendan: Je ne sais pas si l'intention de votre commentaire est d'exprimer un accord, un désaccord ou tout simplement un sidenote à ma réponse.
Doc Brown

Les programmes C écrits par des professionnels sont publiés avec des dépassements de tampon et des plantages. Ainsi, alors qu'un programmeur discipliné peut choisir d'apprendre ces choses , le C que le langage n'enseigne pas intrinsèquement simplement en étant appauvri. Il y a beaucoup de mauvaises façons (et pire, de mélanger plusieurs façons incohérentes) pour faire la gestion des erreurs sans exceptions et créer une structure sans objets, par exemple.
Erik Eidt

@ErikEidt: en effet, mais surtout dans l'écosphère C, il existe de nombreux livres, tutoriels et autres matériels qui traiteront de ces sujets. Par exemple, "Writing Solid Code" de Steve Maguire. Bien sûr, si quelqu'un choisit simplement la première édition de K&R pour apprendre la syntaxe du langage, il ne deviendra probablement pas un meilleur programmeur.
Doc Brown

1

Les deux abstractions de base de l'informatique sont les machines de Turing et le calcul Lambda, et C est un moyen d'expérimenter la vue de calcul de la machine de Turing: principalement une succession d'actions de bas niveau d'où émerge un résultat souhaitable. Mais vous devez garder à l'esprit que C est livré avec son propre modèle de calcul. Ainsi, l'apprentissage de C vous apprendra les détails de bas niveau de la machine abstraite C, qui devient très différente des architectures réelles. L'une des premières choses que j'ai apprises en C était de ne jamais essayer de déjouer le compilateur en appliquant des astuces "intelligentes", et il semble que la tendance soit de plus en plus d'optimisations dans les compilateurs. Comme dans d'autres langages de haut niveau, lorsque vous écrivez en C, les compilateurs comprennent en quelque sorte ce que vous attendez de la machine C abstraite et la réalisent sur le matériel réel,

Donc, ce que je veux dire, c'est que l'apprentissage de C ne va pas nécessairement vous donner une bonne image de ce qui se passe réellement dans le matériel. "C est proche de la machine" doit être compris comme "plus proche que la plupart des langages de niveau supérieur". L'apprentissage direct de l'architecture logicielle sera plus gratifiant si vous voulez une image plus précise de "comment cela fonctionne".

D'un autre côté, l'apprentissage du C peut vous familiariser avec la programmation système, les types de bas niveau, les pointeurs et en particulier l'allocation de mémoire. En ce qui concerne l'apprentissage des algorithmes et de la structure des données, je n'ai pas d'avantage à les apprendre en C plutôt que dans d'autres langages.


1
Alors, qu'est
Philip Kendall

2
Je pense que la réponse implicite est: " Rien , du moins pas les choses que les promoteurs prétendent habituellement". Voilà comment je comprends la réponse de toute façon.
Jörg W Mittag

-3

C'est une question très ouverte, peut-être pas une réponse concluante. Vous pouvez apprendre à peu près tout dans toutes les langues à condition de comprendre les éléments internes du cadre linguistique. C vous oblige à comprendre les détails inférieurs car il a été principalement conçu pour écrire un système d'exploitation. Même après tant d'années, il reste l'un des langages les plus utilisés principalement grâce aux systèmes embarqués et aux projets open source. Alors, la question est ce que vous voulez apprendre? Et dans quel domaine?

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.