KeatsPeeks
Creo que tengo un conocimiento avanzado de C++ y me gustaría aprender C.
Hay muchos recursos para ayudar a las personas que pasan de C a C++, pero no he encontrado nada útil para hacer lo contrario.
Específicamente:
- ¿Existen bibliotecas de uso general ampliamente utilizadas que todo programador de C debería conocer (como boost para C++)?
- ¿Cuáles son los modismos de C más importantes (como RAII para C++)?
- ¿Debo aprender C99 y usarlo, o seguir con C89?
- ¿Algún peligro/trampa para un desarrollador de C++?
- ¿Algo más útil que saber?
cuarc
Ya hay mucho aquí, así que tal vez esto sea solo una adición menor, pero esto es lo que encuentro que son las diferencias más grandes.
Biblioteca:
- Pongo esto primero, porque en mi opinión, esta es la mayor diferencia en la práctica. La biblioteca estándar de C es muy (!) escasa. Ofrece un mínimo de servicios. Para todo lo demás, tiene que hacer su propio rollo o encontrar una biblioteca para usar (y mucha gente lo hace). Tiene E/S de archivos y algunas funciones de cadena y matemáticas muy básicas. Para todo lo demás, debe hacer el suyo propio o encontrar una biblioteca para usar. Encuentro que extraño mucho los contenedores extendidos (especialmente los mapas) cuando paso de C++ a C, pero hay muchos otros.
Modismos:
- Ambos lenguajes tienen administración manual de memoria (recursos), pero C ++ le brinda algunas herramientas para ocultar la necesidad. En C, se encontrará rastreando los recursos a mano con mucha más frecuencia, y tiene que acostumbrarse a eso. Ejemplos particulares son arreglos y cadenas (C++
vector
ystring
le ahorrará mucho trabajo), punteros inteligentes (realmente no puede hacer “punteros inteligentes” como tales en C. Usted pueden hacer el conteo de referencias, pero usted mismo tiene que subir y bajar el conteo de referencias, lo cual es muy propenso a errores (la razón por la que se agregaron punteros inteligentes a C++ en primer lugar), y la falta de RAII en general, que notará en todas partes si están acostumbrados al estilo moderno de programación C++.- Tienes que ser explícito sobre la construcción y la destrucción. Puede discutir sobre los méritos de las fallas de esto, pero como resultado hay un código mucho más explícito.
- Manejo de errores. Las excepciones de C ++ pueden ser difíciles de hacer bien, por lo que no todos las usan, pero si las usa, descubrirá que debe prestar mucha atención a cómo notifica los errores. Necesitar verificar los valores de retorno en todas las llamadas importantes (algunos argumentarían todos llamadas) requiere mucha disciplina y mucho código C no lo hace.
- Las cadenas (y las matrices en general) no tienen sus tamaños. Tienes que pasar muchos parámetros adicionales en C para lidiar con esto.
- Sin espacios de nombres, debe administrar su espacio de nombres global con cuidado.
- No hay vinculación explícita de funciones a tipos como ocurre con
class
en C++. Tienes que mantener una convención de prefijar todo lo que quieras asociado con un tipo.
- No hay vinculación explícita de funciones a tipos como ocurre con
- Verás muchas más macros. Las macros se usan en C en muchos lugares donde C++ tiene características de lenguaje para hacer lo mismo, especialmente constantes simbólicas (C tiene
enum
pero muchos usos de código más antiguos#define
en su lugar), y para genéricos (donde C++ usa plantillas).
Consejo:
- Considere encontrar una biblioteca extendida para uso general. Echa un vistazo a Fácil o ABR.
- Incluso si no desea una biblioteca completa, considere encontrar un mapa/diccionario/tabla hash para uso general. También considere agrupar un tipo de “cadena” básico que contenga un tamaño.
- Acostúmbrate a poner prefijos de módulo o “clase” en todos los nombres públicos. Esto es un poco tedioso pero te ahorrará muchos dolores de cabeza.
-
Haga un uso intensivo de la declaración directa para hacer que los tipos sean opacos. ¿Dónde en C++ podría tener datos privados en un encabezado y confiar en ellos?
private
está impidiendo el acceso, en C desea insertar los detalles de implementación en los archivos de origen tanto como sea posible. (En mi opinión, también desea hacer esto en C ++, pero C lo hace más fácil, por lo que más personas lo hacen).C++ revela la implementación en el encabezado, aunque técnicamente la oculta del acceso fuera de la clase.
// C.hh class C { public: void method1(); int method2(); private: int value1; char * value2; };
C inserta la definición de ‘clase’ en el archivo fuente. El encabezado es todas las declaraciones hacia adelante.
// C.h typedef struct C C; // forward declaration void c_method1(C *); int c_method2(C *); // C.c struct C { int value1; char * value2; };
-
En la parte del ‘puntero inteligente’, realmente no puedes hacer eso en C. Puedes hacer un conteo manual de referencias para la memoria u otros recursos, pero eso es tan inteligente como… bueno, no inteligente en absoluto. Creo que debería reformularlo como ‘recuento de referencias’ (tenga en cuenta que
scoped_ptr
yunique_ptr
también son punteros inteligentes, en C la gestión de la memoria es manual, no inteligente)– David Rodríguez – dribeas
17 de diciembre de 2009 a las 23:18
-
@dribeas: De acuerdo. Estaba tratando de hacer referencia a “punteros inteligentes” como el término usado en C ++ para que sea obvio lo que estaba discutiendo, pero estoy de acuerdo en que realmente no existe tal cosa en C. Editado.
– quark
21 de diciembre de 2009 a las 16:40
Fácil es un buen punto de partida para el C moderno y lo acostumbra a conceptos como los tipos opacos y la orientación a semiobjetos, que son estilísticamente comunes en el C moderno. En el otro extremo del espectro, las API POSIX estándar son una especie de C “clásico”.
La brecha más grande al pasar de C++ a C no es la sintaxis, es el idioma y allí, como C++, hay diferentes escuelas de programación. Escribirá C bastante diferente si está haciendo un controlador de dispositivo frente a, por ejemplo, un analizador XML.
-
Echaré un vistazo a GLib con seguridad (lo he visto mencionado aquí y allá muchas veces).
– KeatsPeeks
16 de diciembre de 2009 a las 20:51
P5. ¿Algo más útil que saber?
Compre una copia de K&R2 y léala. En términos de costo por página, probablemente sea el libro de computación más caro que comprará con su propio dinero, pero le dará una profunda apreciación de C y los procesos de pensamiento que se incluyeron en él. Hacer los ejercicios también perfeccionará sus habilidades y lo acostumbrará a lo que está disponible en el lenguaje en lugar de C++.
-
¡Sigue siendo mi ideal de lo que debería ser un libro de texto de lenguaje informático, después de todos estos años!
– luego
16 de diciembre de 2009 a las 16:56
-
No estoy muy seguro de si esto realmente le enseñará mucho. Por lo que recuerdo, el libro cubre principalmente ideas y sintaxis de C bastante básicas, que el OP ya conoce.
– Edan Maor
16 de diciembre de 2009 a las 17:34
-
De hecho, pero voy a necesitar un libro de referencia de todos modos, así que gracias por el consejo, incluso si no es realmente lo que pedí.
– KeatsPeeks
16 de diciembre de 2009 a las 20:49
-
@Edan Maor: si conoce C++, conoce la sintaxis de C. No necesariamente conoce las ideas C. K&R2 es muy compacto (una vez tuve un instructor de Ingeniería Mecánica que literalmente me recomendó cualquier otra cosa), y no es una buena opción para aprender a programar, pero para alguien que sabe programar es una gran introducción y referencia rápida.
–David Thornley
18 de diciembre de 2009 a las 16:58
ataúd de jerry
Tomando sus preguntas en orden:
- Desafortunadamente, no hay nada como Boost para C.
- Nada que sea realmente del orden de RAII tampoco.
- El único compilador que intenta implementar C99 es Comeau.
- Muchos de ellos por todos lados, me temo.
- Bastante. C tiene una mentalidad bastante diferente a la de C.
Algunos de ellos pueden parecer bastante concisos, pero así es la vida. Hay algunas bibliotecas buenas para C, pero en ningún lugar como Boost se han recopilado juntas o se les ha dado una interfaz relativamente uniforme como lo ha hecho Boost para C++.
Hay muchos modismos, pero muchos de ellos se relacionan con la forma en que edita su código, como una especie de imitación de RAII al escribir un fopen()
y una correspondencia fclose()
en rápida sucesión, y solo después escribiendo el código en el medio para procesar los datos.
Los escollos/trampas que acechan en cada esquina provienen principalmente de la falta de estructuras de datos dinámicas como cadenas y vectores, por lo que con frecuencia tiene que escribir esas cosas usted mismo. Sin sobrecarga de operadores, constructores, etc., es considerablemente más difícil hacerlos realmente de propósito general. Muchas bibliotecas los tienen, pero terminas lanzando los tuyos de todos modos porque:
- la biblioteca no hace exactamente lo que usted quiere, o
- usar la biblioteca es más trabajo de lo que vale.
La diferencia de mentalidad es casi con certeza lo más importante, al menos para mí. Cuando escribo C++, concentro casi todo mi esfuerzo real en diseñar las interfaces más limpias posibles, y tiendo a tratar la implementación de una interfaz como casi código desechable. En su mayor parte, no planeo hacer ajustes menores a esa parte del código; siempre que la interfaz sea buena, reemplazar toda la implementación suele ser lo suficientemente fácil como para que no me preocupe mucho.
En C, parece (al menos para mí) mucho más difícil separar la interfaz de la implementación de manera tan completa o limpia. Como tal, tiendo a pasar mucho más tiempo tratando de implementar cada parte del código de la manera más limpia posible, porque los cambios posteriores tienden a ser más difíciles y desechar y reemplazar piezas que no son muy buenas tiene muchas menos probabilidades de funcionar. sale muy bien
Editar (ya que la gente ha planteado preguntas sobre la compatibilidad con C99): si bien mi declaración sobre la falta de compatibilidad con C99 puede parecer dura, el hecho es que es verdad.
MS VC++: es compatible con C95 y tiene un par de características de C99 (por ejemplo, delimitadores de comentarios al estilo de C++), principalmente porque C99 estandarizó lo que tenían anteriormente como una extensión.
Gnu: De acuerdo con C99 Características Estado página, la iteración más reciente de gcc (4.4) tiene algunas características de C99, pero algunas (incluidos los VLA) se caracterizan como “rotas” y otras como “faltantes”. Algunas de las “características” que faltan son realmente completas áreasno características individuales.
PCC: El sitio PCC reclama la conformidad con C99 solo como una meta para el futuro, no como una realidad presente.
Embarcadero Technologies (nee Borland) no parece decir nada sobre la conformidad con C99 en absoluto; por lo que parece, la última vez que trabajaron en el compilador de C bien pudo haber sido antes de que se lanzara C99.
microsoft declara abiertamente que no tienen planes actuales para admitir C99, y que ni siquiera lo considerarán hasta que se lance VS 2010. Aunque no puedo encontrar ninguna declaración pública al respecto, Embarcadero parece más o menos lo mismo: ningún indicio de un plan actual, y ni siquiera que van a considerar trabajar en él en el corto plazo.
Si bien gcc y pcc parecen tener planes, actualmente son solo eso: planes. Ambos admiten abiertamente que, en la actualidad, ni siquiera están muy cerca de cumplir con C99.
Aquí está un referencia rápida de algunas de las cosas más importantes que querrá saber.
carl smotricz
Este es un consejo que no pediste: creo que la mayoría de los empleadores potenciales dan por sentado que si sabes C++, sabes C. Aprender los puntos más finos de C, aunque es un ejercicio académico interesante, en mi opinión, no te dará mucha elegibilidad. puntos.
Si alguna vez termina en una posición en la que necesita hacer C, se dará cuenta de las diferencias lo suficientemente rápido.
Pero no me escuches. Era demasiado perezoso y estúpido para aprender C++ 🙂
vitaly.vch
¿Algo más útil que saber?
C99 no es un subconjunto de c ++ ninguna revisión, sino un lenguaje separado.
-
C90 no es completamente un subconjunto de C ++ y, en cualquier caso, escribiría programas de manera diferente en C90 y C ++.
–David Thornley
18 de diciembre de 2009 a las 16:55