J'ai souvent entendu des gens suggérer d'étudier C. pour comprendre les performances de l'ordinateur. Est-ce une bonne idée? Êtes-vous sûr Je vais immédiatement décrire les conclusions de l'article, juste pour une clarté absolue:
- C n'est pas comment l'ordinateur fonctionne.
- Je ne pense pas que la plupart des gens parlent littéralement, donc peu importe.
- Comprendre le contexte signifie que l'apprentissage du C pour cette raison peut toujours avoir du sens, selon vos objectifs.
J'ai l'intention d'écrire deux autres articles avec une explication plus détaillée des conclusions, mais c'est déjà suffisant. Ajoutez des liens ici lorsque les articles seront publiés.
J'ai souvent entendu des gens dire ceci:
En étudiant C, vous pouvez comprendre le fonctionnement des ordinateurs.
Je ne pense pas que l'idée soit initialement erronée, mais elle a quelques réserves. Si vous les gardez à l'esprit, cela pourrait très bien être une stratégie viable pour apprendre des choses nouvelles et importantes. Cependant, je vois rarement des gens discuter de ces réserves en détail, alors j'écris cet article pour fournir, à mon avis, un contexte très nécessaire ... Si vous songez à apprendre le C pour comprendre le fonctionnement de votre ordinateur, cet article est pour vous. J'espère qu'elle vous aidera à le découvrir.
Avant de vraiment commencer, je voudrais dire encore une chose: si vous voulez apprendre le C, alors étudiez! L'apprentissage est super. L'apprentissage du C est devenu très important pour ma compréhension de l'informatique et ma carrière. Apprendre ce langage et sa place dans l'histoire d'un langage de programmation fera de vous un meilleur programmeur. Vous n'avez besoin d'aucune excuse. Apprenez des choses juste pour le plaisir d'apprendre. Cet article est destiné à être un guide pour comprendre la vérité, il ne traite pas de l'opportunité d'étudier C.
Tout d'abord, à qui cette idée est généralement recommandée. Si vous essayez de «savoir comment fonctionnent les ordinateurs», il va sans dire que vous ne comprenez pas cela pour le moment. Quels programmeurs ne comprennent pas comment fonctionnent les ordinateurs? J'ai essentiellement vu que ce sentiment venait de personnes qui programment principalement dans des langages de «scriptage» typés dynamiquement comme Ruby, Python ou JavaScript. Ils sont censés «ne pas savoir comment fonctionnent les ordinateurs» car ces langages fonctionnent à l'intérieur d'une machine virtuelle, où seule la sémantique de la machine virtuelle importe. Au final, l'idée même d'une machine virtuelle est de fournir la portabilité. Le but n'est pas de dépendre de l'équipement sur lequel la VM fonctionne.
Il n'y a qu'un seul problème: C fonctionne
également à l' intérieur d'une machine virtuelle.
Machine abstraite C
D'après la
spécification C99 , section 5.1.2.3, «Exécution du programme»:
Les descriptions sémantiques de la présente Norme internationale décrivent le comportement d'une machine abstraite dans laquelle les problèmes d'optimisation ne sont pas pertinents.
À mon avis, c'est la chose la plus importante à comprendre lors de l'apprentissage de C. Le langage ne «décrit pas le fonctionnement d'un ordinateur», mais décrit le fonctionnement d'une «machine C abstraite». Tout le reste important découle de ce concept.
Encore une remarque: ici j'ai choisi C99, qui n'est pas la dernière norme C. Pourquoi? Eh bien, MSVC a ... une prise en charge intéressante du langage C , et je suis un utilisateur Windows ces jours-ci. Oui, vous pouvez exécuter clang
et gcc
sous Windows. Il n'y a pas de grande différence entre C89, C99 et C11 quant à ce dont nous parlons. À un moment donné, vous devez choisir. La version que j'ai mentionnée ici comprend quelques modifications par rapport aux spécifications d'origine.
Vous avez peut-être entendu une autre phrase dans votre discours en C: «C est assembleur portable». Si vous pensez à cette phrase, vous comprendrez que si cela est vrai, alors C ne peut pas correspondre au fonctionnement d'un ordinateur: il existe de nombreux ordinateurs différents avec des architectures différentes. Si C est comme un assembleur qui s'exécute sur différents ordinateurs avec différentes architectures, il ne peut pas fonctionner simultanément exactement comme chacun de ces ordinateurs. Il
doit cacher les détails, sinon il ne sera pas portable!
Néanmoins, je pense que ce fait n'a pas d'importance, car les gens se réfèrent à peine littéralement à "C est la façon dont l'ordinateur fonctionne." Avant de revenir à cela, parlons de la machine C abstraite, et pourquoi beaucoup ne semblent pas comprendre cet aspect de C.
Digression: pourquoi les gens se trompent-ils?
Je ne peux que parler de mon expérience, bien que ce ne soit pas unique.
J'ai appris GW-BASIC, puis C, puis C ++, puis Java. J'ai entendu parler de Java avant de commencer à l'écrire vers 1999, quatre ans après son apparition. Le marketing à cette époque contrastait activement Java et C ++, il se concentrait sur la JVM en tant que plate-forme, et sur le fait que le modèle de machine le distingue du C ++, et donc C. Sun Microsystems n'existe plus, mais le
miroir du
communiqué de presse nous rappelle:
Les applications Java sont indépendantes de la plate-forme; il vous suffit de porter la machine virtuelle Java sur chaque plate-forme. Il agit comme un interprète entre l'ordinateur de l'utilisateur et l'application Java. Une application écrite dans l'environnement Java peut fonctionner n'importe où, éliminant le besoin de porter des applications sur plusieurs plates-formes.
La devise principale était «Écrivez une fois, exécutez partout». Ces deux phrases sont devenues comment j'ai (et beaucoup d'autres) compris Java et comment il diffère de C ++. Java a un interprète, une machine virtuelle Java. Il n'y a pas de machine virtuelle en C ++.
Avec un marketing aussi puissant, la «machine virtuelle» dans l'esprit de nombreuses personnes est devenue synonyme de «grand moteur d'exécution et / ou interprète». Les langues sans cette fonctionnalité étaient trop liées à un ordinateur spécifique et nécessitaient un portage car elles n'étaient pas vraiment indépendantes de la plate-forme. La principale raison pour laquelle Java existait était un changement dans cette faille C ++.
«Environnement d'exécution», «machine virtuelle» et «machine abstraite» sont des mots différents pour le même concept fondamental. Mais depuis lors, ils ont reçu des connotations différentes en raison d'une légère variation dans la mise en œuvre de ces idées.
Je crois personnellement que ce marketing de 1995 est la raison pour laquelle les programmeurs comprennent encore mal la nature de C.
Cette déclaration est-elle donc fausse? Pourquoi Sun Microsystems dépenserait-il des millions et des millions de dollars pour promouvoir des mensonges? Si C est également basé sur une machine abstraite qui offre une portabilité multiplateforme, pourquoi avons-nous besoin de Java? Je pense que c'est la clé pour comprendre ce que les gens veulent vraiment dire quand ils disent "C est comment l'ordinateur fonctionne".
Que veulent vraiment dire les gens?
Bien que C fonctionne dans le contexte d'une machine virtuelle, il est toujours très différent des langages de type Java. Le soleil n'a pas menti. Pour comprendre, vous devez connaître l'histoire de C.
En 1969, Bell Labs a écrit un système d'exploitation informatique en langage assembleur. En 1970, il a été surnommé UNIX. Au fil du temps, les Bell Labs ont acheté de plus en plus de nouveaux ordinateurs, dont le PDP-11.
Quand est venu le temps de porter Unix sur PDP-11, ils ont décidé d'utiliser un langage de niveau supérieur, ce qui était une idée assez radicale à l'époque. Imaginez qu'aujourd'hui je vous dise: "Je vais écrire un OS en Java" - vous allez probablement rire, bien que l'
idée soit réalisable . La situation (à ma connaissance, je ne vivais pas à l'époque) était à peu près la même. Nous avons considéré un langage appelé B, mais il ne supportait pas certaines des fonctions du PDP-11, et donc ils ont créé un successeur en l'appelant "C" car c'était la prochaine lettre de l'alphabet.
Il n'y avait pas de langue "A"; B a réussi BCPL (Basic Combined Programming Language).
En 1972, le premier compilateur C a été écrit sur PDP-11 et en même temps réécrit UNIX en C. Initialement, ils ne pensaient pas à la portabilité, mais C a gagné en renommée, donc les compilateurs C ont porté sur d'autres systèmes.
En 1978, la première édition du livre "Programming Language C" a été publiée. Affectueusement appelé «K&R», selon les noms de ses auteurs, le livre ne ressemblait pas du tout à la spécification, mais en même temps, décrivait le langage de manière suffisamment détaillée, à la suite de quoi d'autres ont également essayé d'écrire des compilateurs C. Plus tard, cette «version» sera appelée «K&R C».
À mesure que UNIX et C se répandaient, ils étaient tous deux portés sur de nombreux ordinateurs. Dans les années 70 et 80, leur base matérielle ne cessait de croître. De la même manière que C a été créé car B ne prend pas en charge toutes les fonctions de PDP-11, de nombreux compilateurs utilisent des extensions de langage. Comme il n'y avait que K&R et non une spécification, cela était considéré comme acceptable tant que les extensions étaient assez proches. En 1983, l'absence de toute normalisation posait des problèmes. L'ANSI a donc constitué une équipe pour préparer les spécifications. En 1989, la norme C89 est sortie, parfois appelée "ANSI C".
La spécification C a tenté d'unifier ces diverses implémentations sur divers matériels. Ainsi, la machine C abstraite est une sorte de spécification la plus petite possible qui permettrait au même code de fonctionner de la même sur toutes les plateformes. Les implémentations C ont été compilées, pas interprétées, donc il n'y avait pas d'interprète, donc il n'y avait pas de «VM» au sens de 1995. Cependant, les programmes C sont écrits sur cet ordinateur abstrait inexistant, puis le code est converti en assembleur spécifique à l'ordinateur particulier sur lequel le programme s'exécute. Vous ne pouviez pas vous fier à certains détails spécifiques pour écrire du code C. portable. Cela rend l'écriture du C portable très difficile car vous avez peut-être fait une hypothèse spécifique à la plate-forme lors de l'écriture de la version initiale de votre code.
Ceci est mieux illustré par un exemple. Un des principaux types de données en C est
char
, du mot "caractère". Cependant, la machine C abstraite ne détermine pas combien de bits doivent être en caractères. Eh bien, détermine, mais pas par nombre; il détermine la taille de
CHAR_BIT
, qui est une constante. Section 5.2.4.2.1 de la spécification:
Les valeurs indiquées ci-dessous doivent être remplacées par des expressions constantes appropriées ou utilisées dans les directives de prétraitement #if
. ... Les valeurs dans des implémentations spécifiques doivent être égales ou supérieures en magnitude (valeur absolue) à celles données ici avec le même signe.
CHAR_BIT: 8
En d'autres termes, vous savez que
char
est au moins 8 bits, mais les implémentations peuvent être plus grandes. Afin de coder correctement une «machine C abstraite»,
CHAR_BIT
doit être utilisé au lieu de
8
comme taille lors du traitement de
char
. Mais ce n'est pas une sorte de fonction d'interprète, comme nous pensons aux machines virtuelles; c'est une propriété de la façon dont le compilateur traduit le code source en code machine.
Oui, il existe des systèmes où CHAR_BIT
pas 8
.
Ainsi, cette "machine abstraite", bien que techniquement la même idée que la machine virtuelle Java, est plus probablement une construction de compilation pour gérer les compilateurs lors de la création de code assembleur, plutôt qu'une sorte de vérification ou de propriété d'exécution. Le type équivalent en Java est un
byte
, qui est toujours 8 bits, et l'implémentation JVM est chargée de ce qu'il faut faire sur les plates-formes avec plus d'octets. (Je ne sais pas si la JVM fonctionne sur l'une de ces plates-formes, mais c'est ainsi que cela devrait fonctionner.) La machine C abstraite a été créée comme une enveloppe minimale pour divers "matériels", et non comme une sorte de plate-forme en tissu solide, écrite dans un logiciel pour votre code.
Donc, bien que Sun se soit trompé techniquement, dans la pratique, ils signifient un peu ce qu'ils disent littéralement, et ce qu'ils
veulent dire est vrai. Même chose avec la phrase «Apprenez C pour comprendre le fonctionnement des ordinateurs».
Apprenez à mieux comprendre le fonctionnement des ordinateurs
Que
veulent vraiment dire les gens? Dans le contexte de «un rubiste doit-il apprendre le C pour comprendre le fonctionnement des ordinateurs» - c'est un conseil pour descendre «au niveau du fer». C'est-à-dire non seulement pour comprendre comment votre propre programme fonctionne à l'intérieur de la machine virtuelle, mais aussi comment la combinaison du programme et de la VM fonctionne dans le contexte de la machine elle-même.
L'apprentissage C vous
fournira plus de ces détails car la machine abstraite est beaucoup plus proche du matériel ainsi que des abstractions des systèmes d'exploitation. Le langage C est très différent des langages de haut niveau, donc l'apprendre peut en apprendre beaucoup.
Mais il est important de se rappeler que C est essentiellement une
abstraction matérielle et que les abstractions sont imparfaites. Faites attention à ce que fait C ou à son fonctionnement avec la machine elle-même. Si vous allez trop loin, vous rencontrerez sûrement ces différences, ce qui peut causer des problèmes. La plupart des ressources de formation pour C, en particulier aujourd'hui, lorsque l'équipement devient plus homogène, favoriseront l'idée que
c'est ainsi que
fonctionne un ordinateur. Par conséquent, il peut être difficile pour un élève de comprendre ce qui se passe sous le capot et quelle est l'abstraction fournie par C.
Dans cette discussion, nous n'avons même pas abordé d'autres questions. Par exemple, en raison de l'énorme popularité de C, le matériel est devenu plus uniforme car il tend à évoluer vers la sémantique de la machine abstraite C. Si votre architecture est trop différente de la sémantique C, les programmes C peuvent s'exécuter beaucoup plus lentement que les autres. et la vitesse du matériel est souvent mesurée par des tests en C. Cet article est déjà assez long ...
Pour cette raison, je pense qu'une version plus précise de cette déclaration serait «En apprenant le C, vous
en apprendrez
plus sur le fonctionnement des ordinateurs». Je pense vraiment qu'une connaissance approximative de C est utile à de nombreux programmeurs, même s'ils n'écrivent pas eux-mêmes C. L'introduction de C vous donnera également une idée de l'histoire de notre industrie.
Il existe d'autres façons d'explorer ce sujet; C
n'est intrinsèquement pas conçu pour en savoir plus sur un ordinateur, mais c'est une bonne option.
Il y a tellement à apprendre en programmation. Je vous souhaite beaucoup de succès dans ce voyage.