Pourquoi certains programmeurs classent-ils C, Python, C ++ différemment? - concernant le niveau

16

Je prends un cours d'introduction sur python et l'instructeur dit que python est un langage de haut niveau et C et C ++ sont des langages de bas niveau. C'est juste déroutant. Je pensais que C, C ++, Python, Java, etc. étaient tous des langages de haut niveau.

Je lisais des questions à stackoverflow sur C, C ++, etc. et elles semblent toutes se référer à ces langages comme de haut niveau. Il me semble que certains programmeurs utilisent ces termes de manière interchangeable.

athée
la source
1
Comme beaucoup de choses, le niveau haut contre bas est une simplification - utile pour la compréhension, mais potentiellement trompeur si vous oubliez que c'est une simplification. Quel niveau est certainement relatif, comme d'autres l'ont dit. Mais ce n'est pas nécessairement une ligne - il y a différentes directions dans lesquelles vous pouvez résumer (par exemple différents paradigmes). Ce n'est pas parce que vous vous éloignez de l'abstraction de la machine que vous vous dirigez vers une abstraction appropriée pour votre application.
Steve314
Même le point de départ peut varier. Par exemple, IMO le calcul lambda est un niveau d'abstraction très bas - beaucoup abstrait dans la machine, mais c'est une abstraction très simple qui sert de point de départ aux langages fonctionnels pour commencer à construire des abstractions par-dessus. Dans tous les cas, le calcul lambda n'est probablement pas plus proche de l'abstraction idéale pour une application particulière que le code machine.
Steve314

Réponses:

31

Niveau élevé et niveau bas sont des termes relatifs, de sorte que l'utilisation a changé au fil du temps. Dans les années 70, UNIX a fait des vagues parce qu'il montrait qu'un système d'exploitation pouvait être écrit principalement dans un langage de haut niveau: C. À l'époque, C était considéré comme de haut niveau, contrairement à l'assembleur.

De nos jours, C est considéré comme un langage de bas niveau car ni le langage ni les bibliothèques standard ne fournissent aucune des structures de données de type pain et beurre comme les vecteurs, les dictionnaires, les itérateurs, etc. Vous pouvez avoir toutes ces structures dans un programme C, mais vous finirez par les écrire vous-même. Python, Java, etc. sont de haut niveau par rapport à C car bon nombre de ces structures de données standard sont intégrées au langage ou font partie des bibliothèques standard. Le fait de les sortir de la boîte facilite la programmation à un niveau plus abstrait.

C est de bas niveau dans un 2ème sens: il permet une manipulation directe du matériel informatique (au moins aussi directe que l'OS le permet). Les implémentations les plus courantes de Python, Java, etc. sont au moins une étape plus loin du matériel car elles s'exécutent dans une machine virtuelle. Si vous souhaitez manipuler le matériel à partir de Python, vous devrez écrire une extension sur la machine virtuelle Python, généralement en C ou C ++.

C ++ est un cas étrange. Il fournit des tonnes de belles structures de données dans le cadre de la bibliothèque standard, mais il permet également une manipulation de bas niveau du matériel.

Charles E. Grant
la source
3
C ++ n'est pas vraiment un cas étrange, OMI - c'est simplement un langage de niveau mixte. Le niveau d'abstraction que vous obtenez dépend des fonctionnalités que vous utilisez.
Steve314
1
@ Steve314: Oui et non: normalement l'abstraction s'accompagne de la dissimulation d'informations, c'est-à-dire qu'une langue ou une bibliothèque est comme une boîte noire qui fournit une interface, et personne ne veut savoir ce qu'il y a à l'intérieur de la boîte noire. Le C ++ est un peu étrange car il propose des constructions de niveau supérieur mais n'empêche pas le programmeur d'accéder à leur représentation et de les casser. Le C ++ est le seul langage que je connaisse qui n'isole pas les différentes couches d'abstraction (mais il y a peut-être d'autres langages que je ne connais pas).
Giorgio
1
@Giorgio - C ++ vous permet de masquer tout détail d'implémentation - par exemple, de l'intégrer dans les internes privés d'une classe, de sorte que la seule façon officielle de l'utiliser est via l'interface publique de cette classe. Bien sûr, vous pouvez enfreindre les règles et brouiller votre mémoire autant que vous le souhaitez - mais en pratique, vous pouvez le faire dans n'importe quel langage prenant en charge le développement d'applications réelles.
Steve314
@Giorgio - Prenez par exemple Haskell. "Dangereux" dans ce cas a tendance à signifier non-référentiellement transparent (comme dans unsafePerformIO). Il existe des IOReftypes, mais il n'y a pas d'équivalent de reinterpret_castce que je connais et pas d'équivalent d'arithmétique de pointeur. Mais cela ne signifie pas qu'il est à l'abri des gens qui piratent la mémoire. Pour être un langage pratique, Haskell doit s'interfacer avec des systèmes d'exploitation et des bibliothèques du monde réel. Il a une "interface de fonction étrangère". Si je veux vraiment le subvertir, tout ce que je dois faire est d'utiliser le FFI pour écrire les fonctions de subversion primitives.
Steve314
@Giorgio - Bien sûr, j'ai peut-être du mal à trouver les valeurs que je veux corrompre en mémoire, mais la même chose peut s'appliquer en C ++, selon la façon dont je les ai cachées. Par exemple, je pourrais utiliser un PIMPL . Si je ne fournis alors que le code objet et l'en-tête de la bibliothèque qui comprend ce que cela signifie, le subversif potentiel doit inverser l'ingénierie de ce code objet pour comprendre quoi subvertir et comment.
Steve314
8

Pensez à cela en termes d'échelle mobile, des langues de bas niveau jusqu'aux langues de haut niveau. À mesure qu'une langue monte dans l'échelle, de BAS à ÉLEVÉ, la langue fournit de plus en plus d'abstraction à partir de l'interface spécifique avec l'ordinateur.

Les langages de bas niveau sont écrits pour diriger explicitement l'ordinateur - pensez au code machine et au code assembleur.

Les langages de haut niveau tentent d'abstraire les moindres détails (en particulier l'allocation de mémoire et la libération de mémoire). L'idée est de fournir une interface plus "naturelle" à la programmation et, espérons-le, de permettre au programmeur de se concentrer sur la conception et la production.

De nos jours, C est considéré comme un langage de niveau BAS. Il contient encore quelques abstractions importantes du code machine et du code assembleur, il est donc techniquement plus élevé que ceux-ci. Cependant, il fournit toujours un adressage direct de la mémoire et ne fournit pas de récupération de place. Ce sont donc des détails pour lesquels un programmeur doit concevoir.

Comparez cela à d'autres langages tels que Python, Ruby ou Haskell et vous avez une interface beaucoup plus obscure. Ces langages ont de grandes bibliothèques de code qui résument la plupart des commandes de l'ordinateur. Vous êtes-vous déjà demandé ce qui arrive à une variable en Python lorsque vous quittez la portée locale d'une fonction ou la supprimez? Probablement pas vrai? Et c'est parce que dans une langue de haut niveau, vous n'avez pas à le faire! Ils s'occupent de l'allocation / libération de mémoire pour vous.

Les langages de haut niveau ont l'avantage de la fonction. Ils nous permettent de concevoir et de développer librement (et en toute sécurité!).

Les langues de niveau BAS ont l'avantage de la vitesse dans la plupart des cas. L'interprétation du code de haut niveau a un coût. De plus, c'est plutôt sympa d'écrire quelque chose en «speek informatique».

J'espère que cela t'aides

Nick Burns
la source
5

De haut niveau par rapport à bas niveau n'est pas une chose en noir et blanc, mais une échelle continue. Les termes sont utilisés pour décrire la proximité d'un langage de programmation avec le matériel; plus le niveau est élevé, plus il éloigne le matériel.

Le niveau le plus bas, évidemment, est le code machine binaire - c'est la représentation exacte que le système d'exploitation charge et envoie au CPU. L'assemblage est le premier niveau d'abstraction construit au-dessus: au lieu du code binaire, on écrit des mnémoïques, des codes symboliques lisibles par l'homme qui représentent des instructions machine binaires. C'est ce que les gens utilisaient pour la programmation des systèmes avant UNIX.

C est la prochaine étape dans la chaîne d'abstraction, regroupant des modèles communs dans des constructions de contrôle de flux et en résumé des instructions spécifiques à la machine dans une syntaxe indépendante de la plate-forme, et ces dernières abstractions ont été l'un des principaux facteurs qui ont fait d'UNIX à la fois révolutionnaire et très réussi, car cela signifiait que le même code pouvait être compilé pour n'importe quelle plate-forme sans aucun changement majeur.

C ++ ajoute une autre couche d'abstractions: il ajoute des classes (abstraction des tables vtables et du contexte passant dans une syntaxe OOP), newet delete(regroupement de l'allocation de mémoire et de l'initialisation des variables dans une seule construction), vérification du type à la compilation, modèles (compilation à la sécurité du type métaprogrammation), et un tas de commodités de syntaxe au moment de la compilation comme les espaces de noms, la surcharge des fonctions et des opérateurs, etc.

Python prend un autre grand pas loin du matériel. C ++ donne toujours au programmeur un contrôle total sur l'allocation de mémoire et permet une manipulation directe de la RAM; Python s'occupe de la gestion de la mémoire pour vous. De plus, au lieu de compiler votre code en instructions machine entièrement natives, il l'exécute sur une machine virtuelle; cela entraîne une pénalité de performance (qui peut parfois être lourde, mais n'est généralement pas quelque chose à craindre), mais cela permet également des choses intéressantes qui seraient délicates en C ++ et atrocement difficiles en C, telles que la manipulation de fonctions et de classes à l'exécution temps, obtenir les noms d'objets arbitraires au moment de l'exécution, instancier les classes par nom au moment de l'exécution, patcher les singes, etc. etc.

Ainsi, lorsque les gens divisent des langues en "haut niveau" et "bas niveau", ils tracent une ligne arbitraire quelque part, et cette ligne n'est pas toujours la même. En 1970, la ligne était entre l'assemblage et le C (l'abstraction des instructions machine spécifiques à la plate-forme étant le facteur décisif); en 1987, il se situait peut-être entre C et C ++; aujourd'hui, il peut se situer entre C ++ et Java (avec la gestion automatique de la mémoire comme facteur décisif).

Pour faire court: le niveau élevé est une échelle mobile, et pour les trois langages que vous mentionnez, c'est C <C ++ <Python.

tdammers
la source
Je dirais que haut niveau vs bas niveau n'est pas une échelle, mais plutôt deux échelles distinctes. Le niveau bas se rapporte à la façon dont un langage se rapporte au comportement de la machine, tandis que le niveau élevé se rapporte à sa capacité à fournir une abstraction. C # est plus un langage de haut niveau que C99, mais est également de niveau inférieur au langage défini par la norme C, car le comportement, par exemple, d'utiliser un pointeur "int" pour traiter des valeurs "courtes" dans un tableau deux à un le temps est défini en C #, mais pas en C99.
supercat
3

La frontière entre les langues «bas niveau» et «haut niveau» change de temps en temps.
Par exemple:
À l'époque d'UNIX, C était un langage de haut niveau.
Aujourd'hui, C n'a pas les structures comme les types de mappage (dictionnaires), les itérateurs, etc. que les langages de haut niveau d'aujourd'hui comme Python ont. Ainsi, la ligne a changé et C est maintenant tombé dans le groupe de bas niveau.

Langages de bas niveau:
Ces langages sont "proches" de ce que la machine peut exécuter (le niveau le plus bas étant: le code d'assemblage!).
Lorsque vous travaillez avec ces langages, le programmeur doit penser aux choses de plus bas niveau comme la gestion de la mémoire. Vous êtes proche en ce sens du matériel, que vous devez travailler directement avec lui.

Langages de haut niveau:
ces langages vous éloignent du matériel, car ils gèrent eux-mêmes des choses comme la mémoire. Lorsque vous travaillez avec ces langages, la mémoire est un facteur (évidemment), mais vous ne travaillez pas directement avec le matériel. Au lieu de cela, le langage gère cela, vous éloignant (peut-être plus haut) de l'interface matérielle inférieure.

pradyunsg
la source