2009-05-29 8 views
47

Viniendo de un fondo OO (C#/java) Estoy buscando recursos para aprender a diseñar bien programas C puros.Recursos para aprender el diseño del programa C

Si bien estoy familiarizado con la sintaxis de C, y puedo escribir pequeños programas, no estoy seguro del enfoque que se debe seguir para las aplicaciones más grandes, y qué técnicas emplear. Cualquier cosa que ustedes puedan recomendar.

EDIT: Me alegra abandonar por completo OO para programar en C, mi interés es aprender cómo estructurar un programa sin OO, quiero aprender sobre las buenas formas de diseñar programas en lenguajes de procedimiento tales como C.

+8

Aprendizaje C es probablemente una de las mejores cosas que puede hacer para realmente expandir tu conjunto de habilidades. Sé que probablemente eso no es lo que muchos programadores "modernos" están acostumbrados a escuchar en estos días, pero es verdad. Creo que tu deseo de aprender es un movimiento realmente inteligente. –

+0

pregunta increíble, estoy en la misma posición. C es bastante pequeño, pero cuando escribo aplicaciones más grandes, también estoy atascado en cómo diseñarlas ... –

Respuesta

45

This posting tiene una lista de libros de Unix que incluye la mayor parte del clásico C/Unix funciona. Para la programación C en Windows, el Programming Windows de Petzold es probablemente el mejor comienzo.

Para el diseño del programa C, algunos de los libros de programación de Unix le dirán fragmentos pero no conozco un libro de 'arquitectura de programa C.'

Si estás acostumbrado a java, algunos consejos para la programación C son:

  1. Makeuseofstack. A menudo, cuando llama a un procedimiento, querrá tener variables asignadas en el marco de pila de la persona que llama y pasarles punteros al procedimiento que desea llamar. Esto será sustancialmente más rápido que la asignación dinámica de memoria con malloc() y mucho menos propenso a errores. Haz esto donde sea apropiado.

  2. C no hace garbage collection, tan dinámicamente la asignación de elementos de datos es más incómoda y hay que hacer un seguimiento de ellos para make sure they get freed. variables asignados en la pila (ver 1) son más 'idiomática', donde sean aplicables. Además, no tiene que liberarlos, esto es una bonificación para las variables locales.

  3. A propósito de (2), considere una arquitectura donde sus funciones devuelven un estado o código de error y pasan datos dentro y fuera usando la pila según (1).

  4. Conozca qué setjmp() y longjmp() do. Pueden ser bastante útiles para los mecanismos genéricos del manejador de errores en lugar de la funcionalidad estructurada de manejo de excepciones.

  5. C does not support exceptions. See (3).

  6. Lint es tu amigo. Splint es aún más amigable.

  7. Conozca lo que hace el preprocessor y lo que no debe hacer con él, incluso si puede.

  8. Conozca los pormenores de endian-ness, word alignment, pointer arithmetic y otros arcanos arquitectónicos de bajo nivel. Contrariamente a la opinión popular, estos no son ciencia espacial. Si te sientes con ganas, intenta incursionar en el lenguaje ensamblador y obtener un conocimiento práctico de eso. Hará mucho por su comprensión de lo que está sucediendo en su programa C.

  9. C no tiene ningún concepto de alcance del módulo, por lo que planifica el uso de incluye, declaraciones de prototipos y uso de extern y static para crear ámbitos privados e importar identificadores.

  10. programación

    GUI en C es tedioso en allplatforms.

  11. A propósito de (10) aprender la API C de la lengua al menos un script como Tcl, Lua o Python. En muchos casos el mejor uso de C es como motor central de alto rendimiento en una aplicación que está sustancialmente escrita en otra cosa.

  12. El equivalente de un constructor es una función de inicialización donde se pasa un puntero al elemento que se desea configurar. A menudo puede ver esto en forma de una llamada a la función que se parece al setup_foo(&my_foo). Es mejor separar la asignación de la inicialización, ya que puede usar esta función para inicializar un elemento que haya asignado en la pila. Un principio similar se aplica a los destructores.

  13. La mayoría de las personas encuentran Hungarian notation tan legible como está escrito en húngaro. La excepción a esto son los hablantes húngaros nativos, que normalmente encuentran la notación húngara tan legible como Cuneiform.. Desafortunadamente, la notación húngara se encuentra ampliamente en el software de Windows y todo el API de Win32 lo usa, con los efectos esperados sobre la legibilidad del software escrito en esta plataforma.

  14. C/Unix libros, incluso los muy buenos como los escritos por el difunto W Richard Stevens, tienden a estar disponibles de segunda mano bastante baratos a través del mercado de Amazon. En ningún orden en particular, obtener una copia de K&R, Stevens y APUEUNP 1& 2, la Dragon book,Rochkind,Programming Pearls,Petzold y Richter (si está trabajando en Windows) y cualquiera de los otros C clásico/Unix funciona. Lee, garabatea con un lápiz y generalmente interactúa con los libros.

  15. Hay muchos, muchos buenos recursos C/Unix programming en la web.

  16. Lea y comprenda el Ten Commandments of C Programming y algunas de las metadiscusiones sobre los por qué y los detrás de los mandamientos. Esto muestra su edad hasta cierto punto, aunque la mayor parte sigue siendo relevante y los compiladores oscuros todavía son quite common in the embedded systems world.

  17. Lex and Yacc son tus amigos si quieres escribir analizadores.

  18. Como Navicore points out below (+1), Hanson 'C Interfaces and Implementations' es un diseño de interfaz/implementación desmantelado para arquitectura modular con un montón de ejemplos. De hecho, he oído hablar de este libro y he escuchado cosas buenas sobre él, aunque no puedo decir que lo haya leído.Además de los modismos en C que describí anteriormente, este concepto es posiblemente el núcleo del buen diseño de procedimientos. De hecho, otros lenguajes de procedimiento como Modula-2 realmente hacen que este concepto sea explícito en su diseño. Esto podría ser lo más parecido a un libro 'C Program Architecture' impreso.

  19. Lea el C FAQ.

+2

Estos son definitivamente algunos puntos buenos. Estoy sorprendido de que setjmp y longjmp se mencionen tan prominentemente. Aunque poderoso, el uso de estos dos debería ser bastante raro, ¿no? Si crees que el abuso de goto es malo (la mayoría de la gente lo cree), imagina el abuso de setjmp y longjmp (¡ay!).En cuanto a asselly, agregaría que es importante no solo incursionar en escribir su propio ensamblado, sino también analizar el ensamblado generado por el compilador de C para comprender lo que realmente está sucediendo. –

+1

Setjmp hace un poco más que goto. Arruina el contexto local de la función. Normalmente lo usaría para generar manejadores de errores genéricos en lugar de un mecanismo de excepción estructurado. El consejo es entender cómo funciona este mecanismo. – ConcernedOfTunbridgeWells

+2

En C no hay excepciones como en Java, y usar goto para implementar algo similar es lo correcto. – hlovdal

2

Aquí hay algunos interesting responses de una pregunta diferente con respecto a la programación de OO en C. Hice una publicación sobre un código C con el que trabajé, cuya orientación de objeto básicamente impulsiva se detuvo al no incluir métodos virtuales.

Si estuviera haciendo la codificación C, usaría esta técnica para definir 'objetos'.

Encuentro que mantener Design Patterns en mente siempre es útil y se puede implementar en la mayoría de los idiomas.

Aquí hay un buen PDF sobre object oriented C programming.

+1

Si quieres hacer OO en C, realmente deberías usar C++. Si desea usar C, debe escribir un código de procedimiento agradable y claro. –

+1

"Si desea utilizar C, debe escribir un código de procedimiento agradable y claro". ¿Podría recomendar algún recurso para aprender a hacer esto? Este es el tipo de cosa que estoy buscando. – Kingsley

+0

Hay casos donde se requiere el uso de C. No todos los procesadores tienen compiladores de C++, especialmente si se está moviendo a una situación incrustada. Cuando trabaje con código para ejecutar en hardware de bajo nivel, aún le conviene codificarlo en C y luego tener un contenedor de C++. – Kieveli

2

minix por Tanenbaum

6

Mis preocupaciones que van desde OO de nuevo a C se trataron en "C Interfaces and Implementations" de David Hanson.

C Interfaces and Implementations

serio, su enfoque hecho una gran diferencia en evitar accidentalmente la construcción de la gran bola de hilo que muchos sistemas no-oo terminan siendo.

+1

+1 - gracias por recordarme. He oído hablar de este libro, pero nunca lo he leído. Interfaces/implementaciones es una metodología de procedimiento clave y se hace explícita en Modula-2. Apuntaré a esto en mi publicación ya que creo que esto puede ser lo más parecido a un libro de 'arquitectura C' del que haya oído hablar alguna vez. Buen pensamiento 99; -} – ConcernedOfTunbridgeWells

0

Si bien está escrito como un texto un tanto independiente del idioma, Code Complete proporciona una gran cantidad de orientación sobre la estructura del código y la organización, junto con las prácticas de construcción.

1

¿Aplicaciones más grandes? La fortaleza de C es cuando tienes que lidiar con cosas de bajo nivel como controladores de dispositivos, programadores y otras cosas con el sistema operativo.

Usted puede hacer C que opera como OO, pero que se sentirá utlimately como un ejercicio de re-inventar la rueda ..

+0

Esas pueden ser aplicaciones bastante grandes, sé por ejemplo que el Kernel de Linux está escrito en C, pero básicamente estoy pidiendo información sobre técnicas sobre cómo se estructura un programa C una vez que se superan las 500 líneas . Sé que muchas personas parecen haber leído mal la pregunta y piensan que quiero usar OO en C, pero en realidad estoy interesado en TODAS las técnicas que se pueden usar para estructurar programas C más grandes. – Kingsley

+0

Oh, bueno, un enfoque común es intentar dividir la aplicación en módulos y luego asignar cada módulo a un archivo .c, 'publicitar' sus méritos en archivos de encabezado (.h) y luego usar #includes para resolver la fuente dependencias. Funciona bastante bien hasta algunos KLOC. Donde las cosas suelen ir en forma de pera es cuando las dependencias se descontrolan, y los archivos .h comienzan a incluir otros archivos .h, o se necesitan varios directorios de origen, o el último horror, alguien comienza a poner declaraciones de variables en archivos .h. – JustJeff

1

Una cosa menor es ordenar sus archivos .c "hacia atrás" - es decir, poner principal() en la parte inferior del archivo, y siempre asegúrese de que las funciones locales (las que no están en su archivo .h, que acaba de escribir para usar en ese archivo) vivan en el mismo lugar donde se usaron por primera vez. Esto significa que no tiene que escribir prototipos para ellos, que es una cosa menos para jugar si tiene que cambiar su API.

Entonces, como un bono, el comando 'gD' en vim siempre ir a la definición de una función, si está en el mismo archivo :)

+1

Además de tener que mantener el prototipo y el cuerpo sincronizados, un buen bloque de prototipos a la cabeza de un archivo .c es una documentación útil para los contenidos. – ConcernedOfTunbridgeWells