Quels exemples spécifiques sont là de savoir C vous un meilleur programmeur de haut niveau?

StackOverflow https://stackoverflow.com/questions/2077913

  •  21-09-2019
  •  | 
  •  

Question

Je connais l'existence de questions telles que celui-ci et Retour aux notions de base et de voir de nombreuses questions similaires sur SO, J'ai commencé à se demander quels sont les exemples concrets de situations où la connaissance des choses comme C peut vous faire un meilleur programmeur de haut niveau.

Ce que je veux savoir est s'il y a beaucoup d'exemples. Plusieurs fois, la réponse à cette question est quelque chose comme « La connaissance C vous donne une meilleure idée de ce qui se passe sous les couvertures » ou « Vous avez besoin d'une base solide pour votre programme », et ces réponses n'ont pas beaucoup de sens. Je veux comprendre les différentes manières spécifiques dont vous bénéficierez de connaître les concepts de bas niveau,

Joel a donné quelques exemples: bases de données binaires vs XML et les chaînes. Mais deux exemples ne justifient pas vraiment l'apprentissage C et / ou de l'Assemblée. Donc, ma question est la suivante: Quels exemples spécifiques sont là de savoir C vous un meilleur programmeur de haut niveau

Était-ce utile?

La solution

Mon expérience avec les étudiants de l'enseignement et travailler avec des gens qui ne ont étudié les langages de haut niveau est qu'ils ont tendance à penser à un certain niveau d'abstraction, et ils supposent que « tout est gratuit ». Ils peuvent devenir très programmeurs compétents, mais finalement ils doivent faire face à un code qui a des problèmes de performance et il vient de les mordre.

Lorsque vous travaillez beaucoup avec C, vous ne pensez sur l'allocation de mémoire. Vous pensez souvent à la mise en page de la mémoire (et la localité de cache si c'est un problème). Vous comprenez comment et pourquoi certaines opérations graphiques coûtent juste beaucoup. Comment certains comportements de prise efficaces ou inefficaces sont. Comment les tampons de travail, etc. Je pense que l'utilisation des abstractions dans un langage de haut niveau lorsque vous ne savez comment il est mis en œuvre en dessous des couvertures parfois vous donne « cette sauce secrète supplémentaire » en pensant à la performance.

Par exemple, Java a un éboueur et vous ne pouvez pas affecter directement les choses à la mémoire directement. Et pourtant, vous pouvez faire certains choix de conception (par exemple, avec des structures de données personnalisées) qui affectent la performance en raison des mêmes raisons que ce serait un problème en C.

En outre, et plus généralement, je pense qu'il est important pour un programmeur de pouvoir de connaître non seulement la notation grand-O (que la plupart des écoles enseignent), mais que dans les applications de la vie réelle de la constante est aussi importante (que les écoles essaient ignorer). Mon expérience anecdotique est que les gens ayant des compétences dans les deux niveaux de langue ont tendance à avoir une meilleure compréhension de la constante, peut-être à cause de ce que je viens de décrire.

En outre, de nombreux systèmes de haut niveau que je l'ai vu l'interface avec les bibliothèques de niveau inférieur et infrastructures. Par exemple, certaines communications, bases de données ou bibliothèques graphiques. Certains pilotes de certains périphériques, etc. Si vous êtes un programmeur de puissance, vous pouvez eventially s'aventurer là-bas et il aide à au moins avoir une idée de ce qui se passe.

Autres conseils

La connaissance des choses de bas niveau peut aider beaucoup.

Pour devenir un pilote de course, vous devez apprendre et comprendre la physique de base de la façon dont l'adhérence des pneus la route. Tout le monde peut apprendre à conduire assez vite, mais il faut une bonne compréhension des choses « bas niveau » (forces et par friction, les lignes de course, bien manette des gaz et commande des freins, etc.) pour obtenir ces quelques derniers pour cent de la performance qui vous permettra de gagner la course.

Par exemple, si vous comprenez comment l'architecture du processeur fonctionne sur votre ordinateur, vous pouvez écrire du code qui fonctionne mieux avec elle (par exemple, si vous savez que vous avez une certaine taille du cache du processeur ou un certain nombre d'octets dans chaque ligne de cache du processeur , vous pouvez organiser vos structures de données et la façon dont vous les accès à tirer le meilleur parti du cache - par exemple, le traitement de nombreux éléments d'un tableau en ordre est souvent plus rapide que le traitement des éléments aléatoires, en raison du cache du processeur). Si vous avez un ordinateur multi-core, puis comprendre comment les techniques de bas niveau comme le filetage travail peut a donné d'énormes avantages (comme ne pas comprendre le faible niveau peut conduire à la catastrophe dans le filetage).

Si vous comprenez comment fonctionne le disque d'E / S et la mise en cache, vous pouvez modifier les opérations de fichiers fonctionnent bien avec elle (par exemple, si vous lisez d'un fichier et d'écrire à un autre, travaillant sur de grands lots de données dans la RAM peut aider à réduire I / O discorde entre les phases de lecture et d'écriture de votre code, et d'améliorer considérablement le débit)

Si vous comprenez comment fonctionnent les fonctions virtuelles, vous pouvez concevoir un code de haut niveau qui utilise des fonctions virtuelles bien . Si elle est utilisée de manière incorrecte, ils peuvent gravement nuire à la performance.

Si vous comprenez comment le dessin est manipulé, vous pouvez utiliser des astuces intelligentes pour améliorer la vitesse de dessin. par exemple. Vous pouvez dessiner un échiquier en tirant alternativement 64 carrés blancs et noirs. Mais il est souvent plus rapide de tirer 32 sqares blancs puis 32 noirs (parce que vous suffit de changer la couleur de dessin deux fois au lieu de 64 fois). Mais vous pouvez réellement tirer tout le tableau noir, puis XOR 4 bandes à travers le conseil d'administration et 4 bandes en bas de la carte en blanc, et cela peut être beaucoup plus rapide encore (2 changements de couleur, et seulement 9 rectangles pour dessiner au lieu de 64). Cette astuce vous enseigne un jeu d'échecs compétences de programmation très important: la pensée latérale. En concevant votre bien algorithme, vous pouvez souvent faire une grande différence à la façon dont votre programme fonctionne.

Comprendre C, ou pour cette matière, tout langage de programmation de bas niveau, vous donne l'occasion de comprendre les choses comme l'utilisation de la mémoire (à savoir pourquoi est-ce une mauvaise chose pour créer plusieurs millions d'objets lourds), comment fonctionnent les pointeurs / références d'objet, etc.

Le problème est que nous avons créé des niveaux toujours de plus en plus d'abstraction, nous nous retrouvons à faire beaucoup de programmation « bloc lego », sans comprendre comment fonctionnent les legos réellement. Et en ayant des ressources presque infinies, nous commençons à traiter la mémoire et des ressources comme l'eau, et ont tendance à résoudre les problèmes en lançant plus de fer à la situation.

Bien que non limité à C, il y a un énorme avantage de travailler à un niveau bas avec beaucoup plus petits, systèmes dont la mémoire comme les processeurs 8 bits Arduino ou vieille école. Il vous permet de vivre à proximité du codage métallique dans un ensemble beaucoup plus accessible, et après avoir passé le temps pressant des applications en 512K, vous vous trouverez l'application de ces compétences à un niveau plus large dans la journée à la programmation de jour.

Ainsi, la langue elle-même n'a pas d'importance, mais ayant une meilleure appréciation de la façon dont tous les bits sont réunis, et la façon de travailler efficacement à un niveau plus proche du matériel est un ensemble de compétences utiles à tout développeur de logiciel.

D'une part, sachant C vous aide à comprendre comment fonctionne la mémoire dans le système d'exploitation et dans d'autres langages de haut niveau. Lorsque votre C # ou des ballons de programme Java sur l'utilisation de la mémoire, la compréhension que les références (qui sont essentiellement des pointeurs) prennent mémoire aussi, et comprendre combien des structures de données sont mises en œuvre (que vous obtenez de faire votre propre en C) vous aide à comprendre que votre dictionnaire est réservait d'énormes quantités de mémoire qui ne sont pas réellement utilisés.

D'autre part, sachant C peut vous aider à comprendre comment utiliser des fonctionnalités plus bas niveau du système d'exploitation. Vous n'avez pas besoin de ce souvent, mais parfois, vous devrez peut-être des fichiers mappés en mémoire, ou d'utiliser marshalling en C # et C va grandement aider à comprendre ce que vous faites quand cela se produit.

Je pense que C a également contribué à ma compréhension des protocoles réseau, mais je ne peux pas mettre mon doigt sur des exemples précis. Je lisais une autre SO question l'autre jour où quelqu'un se plaignait de la façon dont les champs de bit de C sont «fondamentalement inutile et je pensais comment les champs de bits avec élégance C représentent des protocoles de réseau de bas niveau. langues de haut niveau portant sur les structures de bits finissent toujours un gâchis!

En général, plus vous en savez, le meilleur programmeur vous serez.

Cependant, connaissant parfois une autre langue, comme C, peut vous faire faire la mauvaise chose, car il pourrait y avoir une hypothèse qui n'est pas vrai dans une langue de niveau supérieur (comme Python ou PHP). Par exemple, on pourrait supposer que trouver la longueur d'une liste peut être O (N) où N est la longueur de la liste. Toutefois, cela est probablement pas le cas dans de nombreux cas linguistiques de haut niveau. En Python, pour la plupart des choses de la liste comme le coût est O (1).

En savoir davantage sur les détails d'une langue conférera, mais sachant plus en général pourrait conduire à faire des hypothèses incorrectes.

Il suffit de "savoir" C ne serait pas vous faire mieux.

Mais, si vous comprenez la chose, comment le travail des binaires natifs, comment fonctionne CPU avec elle, quelles sont les limites de l'architecture, vous pouvez écrire un code qui est plus facile pour CPU.

Par exemple, comment les caches L1 / L2 affectent votre travail, et comment devriez-vous écrire votre code pour avoir plus de succès dans les caches L1 / L2. Lorsque vous travaillez avec C / C ++ et de faire des optimisations lourdes, vous devrez descendre à ce genre de choses.

Il est pas tant de savoir C comme il est que C est plus proche du métal nu que beaucoup d'autres langues. Vous devez être plus au courant de la façon d'allouer / désallouer la mémoire parce que vous devez le faire vous-même. il vous aide à faire bien comprendre les implications de nombreuses décisions que vous faites.

Pour moi, toute langue est acceptable tant que vous comprenez comment le compilateur / interpréteur (essentiellement) mappe votre code sur la machine. Il est un peu plus facile à faire dans une langue qui expose directement, mais vous devriez pouvoir, avec un peu de lecture, comprendre comment la mémoire est allouée et organisée, quel genre de modèles d'indexation sont plus optimale que d'autres, que les constructions sont plus efficace pour des applications particulières, etc.

Plus important, je pense, est une bonne compréhension des systèmes d'exploitation, les architectures de mémoire, et des algorithmes. Si vous comprenez comment votre algorithme fonctionne, pourquoi il serait préférable de choisir un algorithme ou une structure de données sur une autre (par exemple, HashSet par rapport à la liste), et comment votre code des cartes sur la machine, il ne devrait pas quelle que soit la langue que vous utilisez .

Ceci est mon expérience de la façon dont j'ai appris et moi-même enseigné la programmation, en particulier, la compréhension C, cela va revenir au début des années 1990, donc peut-être un peu ancien, mais la passion et le lecteur est important:

  • Apprendre à comprendre les principes de bas niveau de l'ordinateur, comme la programmation EGA / VGA, voici un lien l'archive Simtel sur le guide du programmeur C à l'ordinateur.
  • Comprendre comment le travail TSR
  • Télécharger l'archive complète des extraits de Bob Stout qui est une grande collection de code C qui fait une chose seulement -. étudier et comprendre, non seulement que la collection d'extraits veut être portable
  • Parcourir au Code international Obfuscated C Concours ( IOCCC ) en ligne, et voir comment le code C peut être abusé et comprendre les intracies de la langue. Le pire abus de code est le gagnant! Télécharger les archives et les étudier.
  • Comme moi, j'ai adoré le fameux C Tutorial de Ponzo qui m'a énormément aidé, malheureusement, l'archive est très difficile à trouver. Si quelqu'un sait où les obtenir, s'il vous plaît laisser un commentaire et je vais modifier cette réponse à inclure le lien. Il y a un autre que je me souvienne - de Coronado [? Générique] C Tutorial, encore une fois, ma mémoire sur celui-ci est floue ...
  • Regardez le journal de Dr. Dobb et C utilisateur Journal - Je ne sais pas si vous peut encore les obtenir en version imprimée, mais ils étaient un classique, peut se rappeler le sentiment de tenir une copie imprimée dans ma main et arrachant la maison pour taper le code pour voir ce qui se passe!
  • Faire une copie ancienne Turbo C v2 que je crois que vous pouvez obtenir à partir borland. com et juste jouer avec la programmation 16bit C pour avoir une idée et le désordre avec les pointeurs ... bien sûr, il est ancien et vieux mais en jouant avec des pointeurs sur elle est très bien.
  • Comprendre et apprendre Pointeurs, lien ici à l'héritage Simtel.net - un lien crucial à la réalisation C Guru'ship faute d'un meilleur mot, aussi, vous trouverez un grand nombre de téléchargements se rapportant à la langue de programmation C - Je me souviens commander réellement Archive Simtel CD et la recherche de la substance C ...

Un couple de choses que vous avez à traiter directement avec en C que d'autres langues abstraites loin de vous inclure la gestion de la mémoire explicite (malloc) et de traiter directement avec les pointeurs.

Ma copine est un semestre de diplôme du MIT (où ils utilisent principalement Java, Scheme et Python) avec un diplôme en informatique, et elle travaille actuellement à une société dont CODEBASE en C ++. Pour les premiers jours, elle avait du mal à comprendre tous les pointeurs / références / etc.

D'autre part, j'ai trouvé passer de C ++ Java très facile, parce que je ne passe confus au sujet de références par valeur vs passe par référence.

De même, en C / C ++, il est beaucoup plus évident que les primitifs ne sont que le compilateur de traiter les mêmes ensembles de bits de différentes manières, par opposition à un langage comme Python ou Ruby où tout est un objet avec ses propres propriétés distinctes.

Un exemple simple (pas tout à fait réaliste) pour illustrer certains des conseils ci-dessus. Considérez l'apparence inoffensive

while(true)
   for(Iterator iter = foo.iterator(); iter.hasNext();)
       bar.doSomething( iter.next() )

ou le niveau encore plus élevé

while(true)
    for(Baz b: foo)
        bar.doSomething(b)

Un problème possible est que chaque fois autour de la while un nouvel objet (le iterator) est créé. Si tout ce que vous aimez est la commodité de programmeur, puis celui-ci est sans aucun doute mieux. Mais si la boucle doit être efficace ou la machine est alors vous ressources limitées sont à peu près à la merci des concepteurs de votre langue de haut niveau.

Par exemple, une plainte typique pour faire de haute performance Java est d'avoir arrêt d'exécution tandis que les déchets (comme tous les objets Iterator attribués) est remis en état. Pas très bon si votre logiciel est chargé de suivre les missiles, pilotage-automatique d'un avion de passagers, ou tout simplement ne pas laisser l'utilisateur se demandant pourquoi l'interface graphique a cessé de répondre.

Une solution possible (toujours dans la langue de niveau supérieur) serait d'affaiblir la commodité du iterator à quelque chose comme

Iterator iter = new Iterator();
while(true)
    for(foo.initAlreadyAllocatedIterator(iter); iter.hasNext();)
       bar.doSomething(iter.next())

Mais cela n'a de sens que si vous aviez une idée sur l'allocation de mémoire ... sinon il ressemble à une API méchant. Commodité coûte toujours quelque part, et sachant des choses plus bas niveau peut vous aider à identifier et à réduire les coûts.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top