¿Qué ejemplos específicos hay de que saber C te convierte en un mejor programador de alto nivel?

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

  •  21-09-2019
  •  | 
  •  

Pregunta

Sé de la existencia de preguntas como Éste y Éste.Dejame explicar.

Afet leyendo el artículo de Joel Volver a lo básico y al ver muchas preguntas similares sobre SO, comencé a preguntarme cuáles son ejemplos específicos de situaciones en las que saber cosas como C puede convertirte en un mejor programador de alto nivel.

Lo que quiero saber es si hay muchos ejemplos de esto.Muchas veces, la respuesta a esta pregunta es algo así como "Conocer C te da una mejor idea de lo que sucede bajo las sábanas" o "Necesitas una base sólida para tu programa", y estas respuestas no tienen mucho significado.Quiero entender las diferentes formas específicas en las que te beneficiarás al conocer conceptos de bajo nivel,

Joel dio un par de ejemplos:Bases de datos binarias vs XML y cadenas.Pero dos ejemplos realmente no justifican aprender C y/o ensamblador.Así que mi pregunta es esta: ¿Qué ejemplos específicos hay de que saber C te convierte en un mejor programador de alto nivel?

¿Fue útil?

Solución

Mi experiencia con los estudiantes de enseñanza y trabajar con personas que solamente estudian lenguajes de alto nivel es que tienden a pensar en un cierto nivel de abstracción, y asumen que "todo viene de forma gratuita". Pueden llegar a ser programadores muy competentes, pero con el tiempo que tienen que hacer frente a un código que tiene problemas de rendimiento y al final lo hará a morderlos.

Cuando se trabaja mucho con C, usted piensa acerca de la asignación de memoria. A menudo se piensa en la capa de memoria (y la localidad caché si eso es un problema). A entender cómo y por qué ciertas operaciones gráficas solo cuestan mucho. ¿Qué tan eficientes o ineficientes ciertos comportamientos son socket. ¿Cómo funcionan los tampones, etc. Siento que el uso de las abstracciones en un lenguaje de alto nivel cuando no sabe cómo se implementa por debajo de las cubiertas a veces le da "que más salsa secreta" cuando se piensa en el rendimiento.

Por ejemplo, Java tiene un recolector de basura y no se puede asignar directamente a la memoria cosas directamente. Y, sin embargo, puede hacer que ciertas opciones de diseño (por ejemplo, con las estructuras de datos personalizados) que afectan al rendimiento debido a las mismas razones que esto sería un problema en C.

También, y de manera más general, siento que es importante para un programador de energía no sólo conocer la notación de orden O (que enseñan la mayoría de las escuelas), pero que en las aplicaciones de la vida real de la constante también es importante (que las escuelas tratan ignorar). Mi experiencia anecdótica es que las personas con habilidades en los dos niveles de lenguaje tienden a tener una mejor comprensión de la constante, tal vez debido a lo que he descrito anteriormente.

Además, muchos sistemas de alto nivel que he visto interfaz con las bibliotecas y de las infraestructuras de nivel inferior. Por ejemplo, algunos de comunicaciones, bases de datos o bibliotecas de gráficos. Algunos controladores para ciertos dispositivos, etc. Si usted es un programador de potencia, que eventially pueden tener que salir allí y esto ayuda a por lo menos tener una idea de lo que está pasando.

Otros consejos

Saber cosas bajo nivel puede ayudar mucho.

Para convertirse en un piloto de carreras, usted tiene que aprender y comprender la física básica de cómo los neumáticos de agarre al camino. Cualquiera puede aprender a conducir muy rápido, pero se necesita una buena comprensión de las de "bajo nivel" cosas (fuerzas y la fricción, las líneas de carreras, el acelerador y el freno fina de control, etc.) para obtener los último porcentaje de rendimiento que le permitirá ganar la carrera.

Por ejemplo, si usted entiende cómo la arquitectura de CPU trabaja en su ordenador, puede escribir código que funcione mejor con ella (por ejemplo, si usted sabe que tiene un cierto tamaño de la caché de la CPU o de un determinado número de bytes en cada línea de caché de CPU , puede organizar sus estructuras de datos y la forma en que se accede a ellos para hacer el mejor uso de la caché - por ejemplo, el procesamiento de muchos elementos de una matriz en orden es a menudo más rápido que el procesamiento de elementos aleatorios, debido a la caché de la CPU). Si usted tiene una computadora multi-núcleo, a continuación, la comprensión de cómo las técnicas de bajo nivel como enhebrar trabajo puede dio enormes beneficios (al igual que no entender el nivel bajo puede conducir al desastre en el roscado).

Si usted entiende cómo funciona el disco de E / S y almacenamiento en caché, puede modificar las operaciones de archivos para trabajar bien con ella (por ejemplo, si se lee de un archivo y escribir a otro, trabajando en grandes lotes de datos en la memoria RAM puede ayudar a reducir I e / S de la discordia entre las fases de lectura y escritura de su código, y mejorará en gran medida el rendimiento)

Si usted entiende cómo funcionan las funciones virtuales, se puede diseñar código de alto nivel que utiliza funciones virtuales y . Si se usan incorrectamente pueden obstaculizar seriamente el rendimiento.

Si usted entiende cómo se maneja el dibujo, puede utilizar trucos inteligentes para mejorar la velocidad de dibujo. p.ej. Puede dibujar un tablero de ajedrez dibujando alternativamente 64 casillas en blanco y negro. Pero a menudo más rápido es dibujar 32 sqares blancos y luego 32 los negros (ya que sólo tiene que cambiar el color de dibujo dos veces en lugar de 64 veces). Pero en realidad se puede dibujar todo el tablero negro, a continuación, XOR 4 rayas en todos los ámbitos y 4 rayas abajo del tablero en blanco, y esto puede ser mucho más rápido todavía (2 cambios de color, y sólo 9 rectángulos para dibujar en lugar de 64). El pensamiento lateral: Este truco tablero de ajedrez que una habilidad de programación muy importante enseña. Mediante el diseño de su bienestar algoritmo, a menudo se puede hacer una gran diferencia para el correcto funcionamiento de su programa.

La comprensión de C, o para el caso, cualquier lenguaje de programación de bajo nivel, le da la oportunidad de entender cosas como el uso de memoria (es decir, ¿por qué es una mala cosa para crear varios millones de objetos pesados), la forma de punteros / referencias objeto de trabajo, etc.

El problema es que a medida que hemos creado cada vez más niveles de abstracción, nos encontramos haciendo una gran cantidad de programación 'bloque de lego', sin entender cómo funcionan los legos en realidad. Y por tener recursos casi infinitas, comenzamos a tratar la memoria y los recursos como el agua, y tienden a resolver problemas por tirar más hierro a la situación.

Aunque no se limita a C, hay un enorme beneficio para trabajar en un nivel bajo con sistemas mucho más pequeños, memoria limitada como el Arduino o procesadores de 8 bits de la vieja escuela. Se le permite disfrutar de cerca de la codificación de metal en un paquete mucho más accesible, y después de pasar tiempo apretando aplicaciones en 512K, se encontrará la aplicación de estas habilidades a un nivel mayor dentro de su día a día de programación.

Así que el lenguaje en sí mismo no es importante, pero tener una apreciación más profunda de cómo todos los bits se juntan, y cómo trabajar con eficacia en un nivel más cercano al hardware es un conjunto de habilidades beneficiosas para cualquier desarrollador de software.

Por un lado, sabiendo C ayuda a entender cómo funciona la memoria en el sistema operativo y en otros lenguajes de alto nivel. Cuando se implementan su C # o globos programa Java en uso de la memoria, la comprensión de que las referencias (que son básicamente sólo punteros) toman la memoria también, y entender cómo muchas de las estructuras de datos (que se obtiene de hacer su propio en C) ayuda a entender que su diccionario está reservando enormes cantidades de memoria que no se usan en realidad.

Por otro lado, sabiendo C puede ayudar a entender cómo hacer uso de las características del sistema operativo de nivel inferior. No es necesario esto a menudo, pero a veces es posible que tenga archivos de memoria asignada, o para usar de clasificación en C # y C será de gran ayuda a entender lo que está haciendo cuando esto sucede.

Creo C también ha ayudado a mi comprensión de los protocolos de red, pero no puedo poner mi dedo en ejemplos específicos. Estaba leyendo otra cuestión de forma, el otro día en el que alguien se quejaba de cómo los campos de bits de C son 'básicamente inútil' y yo estaba pensando cómo elegantemente campos de bits C representan los protocolos de red de bajo nivel. idiomas que se ocupan de las estructuras de bits final siempre un lío de alto nivel!

En general, cuanto más sepa, mejor programador que habrá.

Sin embargo, a veces saber otro idioma, tales como C, puede hacer que hagas las cosas mal, porque puede haber una suposición que no es cierto en un lenguaje de alto nivel (como Python o PHP). Por ejemplo, se podría suponer que la búsqueda de la longitud de una lista podría ser O (N), donde N es la longitud de la lista. Sin embargo, esto probablemente no es el caso en muchos casos lenguajes de alto nivel. En Python, para la mayoría de las cosas-lista como el costo es O (1).

Saber más sobre las características específicas de una lengua va a ayudar, pero conociendo más en general, podría llevar a hacer suposiciones incorrectas.

Justo "saber" C no se haría mejor.

Sin embargo, si usted entiende todo esto, ¿cómo nativa binarios de trabajo, ¿cómo funciona la CPU con ella, ¿cuáles son las limitaciones de la arquitectura, puede escribir un código que es más fácil para la CPU.

Por ejemplo, ¿cómo cachés L1 / L2 afectan a su trabajo, y cómo hay que escribir el código para tener más hits en cachés L1 / L2. Cuando se trabaja con C / C ++ y hacer optimizaciones pesados, tendrá que bajar a ese tipo de cosas.

No es saber tanto C como lo es que C está más cerca del metal descubierto que muchos otros idiomas. Tienes que ser más conscientes de cómo asignar / liberar memoria porque hay que hacerlo usted mismo. Hacerlo usted mismo le ayuda a comprender las implicaciones de las muchas decisiones que se realicen.

Para mí cualquier idioma es aceptable siempre y cuando usted entienda cómo el compilador / intérprete (básicamente) mapea el código en la máquina. Es un poco más fácil de hacer en un lenguaje que expone de manera directa, sino que debe ser capaz de, con un poco de lectura, averiguar cómo se asigna y se organiza la memoria, qué tipo de patrones de indexación son más óptima que otros, lo que las construcciones son más eficiente para aplicaciones particulares, etc.

Lo más importante, creo, es una buena comprensión de los sistemas operativos, arquitecturas de memoria, y algoritmos. Si usted entiende cómo funciona el algoritmo, por lo que sería mejor elegir un algoritmo o estructura de datos a través de otro (por ejemplo, HashSet vs Lista), y cómo su código de mapeo sobre la máquina, no debe importar el idioma que está utilizando .

Esta es mi experiencia de cómo aprendí y enseñé programación, específicamente, la comprensión de C, esto va de nuevo a principios de 1990 por lo que puede ser un poco antiguo, pero la pasión y la unidad es importante:

  • Aprender a comprender los principios de bajo nivel del equipo, como la programación EGA / VGA, aquí hay un enlace al archivo Simtel en la guía del programador C al PC.
  • La comprensión de cómo el trabajo de TSR
  • Descargar todo el archivo de fragmentos de Bob Stout que es una gran colección de código C que hace una cosa Sólo -. estudiarlos y entender, no solo eso, la colección de fragmentos se esfuerza para ser portátil
  • Navegar en el Concurso Internacional ofuscado C Código ( IOCCC ) en línea, y ver cómo el código C puede ser objeto de abusos y entender las intracies de la lengua. El peor abuso de código es el ganador! Descargar los archivos y estudiarlos.
  • Al igual que yo, me encantó el infame C Tutorial de Ponzo que me ayudó muchísimo, por desgracia, el archivo es muy difícil de encontrar. Si alguien sabe de dónde obtenerlos, por favor deje un comentario y voy a modificar esta respuesta para incluir el enlace. No es otro que puedo recordar - Coronado [? Genérico] Tutorial C, de nuevo, mi memoria en este caso es nebuloso ...
  • Mira del Dr. Dobb diario y C Usuario Diario aquí - no sé si todavía puede conseguir en la impresión pero eran un clásico, recuerdo el sentimiento de pertenencia a una copia impresa en la mano y arrancar el hogar de escribir el código para ver qué pasa!
  • Grab una copia antigua de Turbo C v2 que creo que se puede obtener de Borland. com y sólo jugar con la programación de 16 bits C para tener una idea y meterse con los punteros ... seguro que es antigua y vieja pero jugar con los punteros en él está muy bien.
  • entender y aprender punteros, enlazar aquí Simtel.net - un vínculo crucial a la consecución de C Guru'ship a falta de una palabra mejor, también se encuentra una gran cantidad de descargas relacionadas con el lenguaje de programación C - Recuerdo haber hecho el pedido del Archivo Simtel CD y buscando el material C ...

Un par de cosas con las que tienes que lidiar directamente en C y que otros lenguajes te abstraen incluyen la administración de memoria explícita (malloc) y tratar directamente con punteros.

A mi novia le falta un semestre para graduarse del MIT (donde usan principalmente Java, Scheme y Python) con un título en Ciencias de la Computación y actualmente trabaja en una empresa cuyo código base está en C++.Durante los primeros días tuvo dificultades para comprender todos los consejos/referencias/etc.

Por otro lado, me resultó muy fácil pasar de C++ a Java, porque nunca me confundí entre pasar referencias por valor y pasar por referencia.

De manera similar, en C/C++ es mucho más evidente que las primitivas son simplemente el compilador que trata los mismos conjuntos de bits de diferentes maneras, a diferencia de un lenguaje como Python o Ruby donde todo es un objeto con sus propias propiedades distintas.

Un simple (no totalmente realista) ejemplo para ilustrar algunos de los consejos anteriores. Considere la aparentemente inofensiva

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

o el nivel aún más alto

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

Un posible problema aquí es que cada vez que la vuelta de la mientras bucle se crea un nuevo objeto (el iterador). Si todo lo que importa es la conveniencia programador, entonces éste es definitivamente mejor. Pero si el bucle tiene que ser eficiente o la máquina es de recursos limitados, entonces son más o menos a merced de los diseñadores de su lenguaje de alto nivel.

Por ejemplo, se recupera una queja típica para hacer de alto rendimiento de Java está teniendo parada ejecución mientras la basura (como todos aquellos objetos Iterator asignados). No muy bueno si el software se carga con el seguimiento de misiles entrantes, auto-pilotar un avión de pasajeros, o simplemente no dejar que el usuario se preguntaba por qué la interfaz gráfica de usuario ha dejado de responder.

Una posible solución (todavía en el lenguaje de alto nivel) sería debilitar la conveniencia del iterador a algo como

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

Pero esto sólo tendría sentido si tuviera alguna idea acerca de la asignación de memoria ... de lo contrario sólo se ve como una API desagradable. Conveniencia siempre cuesta en alguna parte, y saber cosas de nivel inferior puede ayudarle a identificar y mitigar esos costos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top