Pregunta

Tengo un comentario a una respuesta he publicado en una pregunta C, donde el comentarista sugirió el código debe ser escrito para compilar con un compilador de C ++, ya que la pregunta original se menciona el código debe ser "portátil".

¿Es esta una interpretación común de "C portátil"? Como dije en un comentario adicional a esa respuesta, es totalmente sorprendente para mí, considero portabilidad a significar algo completamente diferente, y ver muy poco beneficio en la escritura de código C que también es legal C ++.

¿Fue útil?

Solución

No. Mi respuesta ¿Por qué limitar artificialmente su código a C? tiene algunos ejemplos de compatible con los estándares C99 no compilan como C ++; C anterior tenía menos diferencias, pero C ++ tiene la tipificación más fuerte y un tratamiento diferente de la lista de argumentos de la función (void).

En cuanto a si existe un beneficio para hacer C 'portátil' en C ++ - el proyecto particular que se hace referencia en esa respuesta era una máquina virtual para un lenguaje basado rasgos, por lo que no encaja en el modelo de objetos de C ++, y tiene una gran cantidad de casos en los que esté tirando de void* de pila del intérprete y luego la conversión a estructuras que representa la distribución de los tipos de objetos incorporados. Para que el código 'portátil' en C ++ tendría que añadir una gran cantidad de moldes, que no hacen nada por la seguridad de tipos.

Otros consejos

La corriente de C ++ (1998) estándar incorpora la (1989) C estándar. Una serie de buenos impresión de seguridad con respecto al tipo a un lado, que significa "bueno" C89 debería compilarse bien en un compilador de C ++.

El problema es que el estándar C actual es la de 1999 (C99) - que es no aún oficialmente parte de la C ++ estándar (que yo sepa) (*). Eso significa que muchas de las características de "mejor" de C99 (long int largo, stdint.h, ...), mientras que apoyaron por muchos compiladores de C ++, son no estrictamente compatible.

"portátil" C significa algo completamente distinto, y tiene poco que ver con las normas oficiales ISO / ANSI. Esto significa que el código no hace suposiciones sobre el medio ambiente de acogida. (El tamaño de int, endianess, funciones no estándar o errno números, cosas por el estilo.)

A partir de una guía de estilo de codificación Una vez escribí para un proyecto multiplataforma:

ADN entre plataformas (no asuma)

  • No hay tipos de datos nativos. Los únicos tipos de datos Usted puede utilizar son los declarados en la biblioteca estándar.
  • char, short, int y largo son de diferente tamaño de cada uno, al igual que float, double y long double.
  • int no es de 32 bits.
  • Char está firmado ni sin firmar.
  • Char no puede contener un número, sólo caracteres.
  • casting un tipo corto en una más larga (int -> largo). Rompe las reglas de alineación de la CPU
  • int e int * son de diferente tamaño.
  • long int * y * son de diferente tamaño (como lo son los punteros a cualquier otro tipo de datos).
  • No recordar los tipos de datos nativos ni siquiera existen?
  • 'a' - 'A' no produce el mismo resultado que 'z' -. 'Z'
  • 'Z' - 'A' no produce el mismo resultado que 'z' - 'a', y no es igual a 25
  • .
  • No se puede hacer nada con un puntero NULL, excepto probar su valor; eliminación de referencias que se colgará el sistema.
  • Aritmética que involucran tanto firmados y los tipos sin signo no funcionan.
  • reglas de alineación para los tipos de datos cambian al azar.
  • disposición interna de los tipos de datos cambia aleatoriamente.
  • comportamiento específico de sobretensión y subdesborda cambios al azar.
  • ABIs Función de llamada cambian aleatoriamente.
  • Operandos se evalúan en orden aleatorio.
  • Sólo el compilador puede solucionar este aleatoriedad. La aleatoriedad va a cambiar con la próxima versión de la CPU / OS / compilador.
  • Para los perros, == y! = Sólo funcionan para los punteros a exactamente el mismo tipo de datos.
  • <,> trabajo sólo para punteros en la misma matriz. Trabajan sólo para carbón de declararse explícitamente sin firmar.
  • Usted todavía recuerda no existen los tipos de datos nativos?
  • size_t (el tipo del valor de retorno de sizeof) no puede convertirse en cualquier otro tipo de datos.
  • ptrdiff_t (el tipo del valor de retorno de sustraer un puntero desde el otro) no puede convertirse en cualquier otro tipo de datos.
  • wchar_t (el tipo de carácter "horizontal", la naturaleza exacta de las cuales se definido por la implementación) no puede convertirse en cualquier otro tipo de datos.
  • Cualquier ..._ t tipo de datos no se puede convertir en cualquier otro tipo de datos

(*) : Esto fue cierto en el momento de la escritura. Las cosas han cambiado un poco con C ++ 11, pero la esencia de mi respuesta es válido.

Portabilidad significa escribir el código para que se compila y tiene el mismo comportamiento utilizando diferentes compiladores y / o en diferentes plataformas (es decir, depender de la conducta dispuesto por la norma (s ISO) siempre que sea posible).

Hacer las cosas para compilar usando el compilador de un lenguaje diferente es un bonito-a-tengo (tal vez), pero no creo que eso es lo que se entiende por la portabilidad. Desde C ++ y C son ahora divergentes más y más, este será más difícil de lograr.

Por otro lado, cuando se escribe código C aun así, evitar el uso de "clase" como un identificador, por ejemplo.

No "portátil" no significa "compila en un compilador de C ++", que significa "compila en cualquier comformant estándar compilador C" con un comportamiento coherente, definido.

Y no se prive de, por ejemplo, mejoras C99 sólo para mantener la compatibilidad C ++.

Sin embargo, mientras se mantiene la compatibilidad no atar sus manos, si se puede evitar el uso de "clase" y "virtual" y el similares, tanto mejor. Si estás escribiendo código abierto, alguien puede querer portar su código en C ++; si está escurra de alquiler, que la empresa / cliente puede querer portar algún momento en el futuro. Hey, tal vez incluso querrá portarlo a C ++ en el futuro

Al ser un "buen administrador" no dejar basura alrededor de la fogata, es sólo un buen karma en lo que hagas.

Y por favor, trate de mantener las incompatibilidades de sus cabeceras. Aunque el código no ha sido portado, las personas pueden necesitar para enlazar con él desde C ++, por lo que tiene un encabezamiento que no utiliza ninguna palabra reservada en C ++, es fresco.

Depende. Si estás haciendo algo que podría ser útil para el usuario de C ++, entonces podría ser una buena idea. Si estás haciendo algo que nunca se necesitarían usuarios de C ++ pero que los usuarios de C puede ser que encuentre conveniente, no se moleste por lo que es compatible con C ++.

Si estás escribiendo un programa que hace algo que mucha gente lo hace, es posible considerar que sea lo más ampliamente utilizable como sea posible. Si estás escribiendo una adición al núcleo de Linux, se puede tirar C ++ compatibilidad por la ventana -. Nunca será necesario

Trate de adivinar quién podría utilizar su código, y si piensa que un montón de fans de C ++ puede encontrar su código útil, considere lo que es amigable C ++. Sin embargo, si usted no cree que la mayoría de los programadores de C ++ que necesitarían (es decir, que es una característica que ya está bastante estandarizado en C ++), no se moleste.

En definitiva, es una práctica común para compilar código C utilizando un compilador de C ++ con el fin de hacer más estricta la comprobación de tipos. Aunque existen herramientas C-específicas de hacerlo como pelusa, es más conveniente utilizar un compilador de C ++.

El uso de un compilador de C ++ para compilar el código C significa que comúnmente se tiene que rodear su incluye con bloques extern "C" para decirle al compilador que no destrozar los nombres de función. Sin embargo, esta no es la sintaxis de C legal. Efectivamente está utilizando sintaxis de C ++ y su código que supuestamente es C, C ++ es en realidad. Asimismo, se tiende a usar "C ++ conveniencia" comienza a arrastrarse en como usar uniones sin nombre.

Si usted necesita para mantener su código estrictamente C, es necesario tener cuidado.

Fwiw, una vez que un proyecto gana un cierto tamaño y cantidad de movimiento, no es improbable que en realidad puede beneficiarse de C compatibilidad ++: incluso si no va a ser portado a C ++ directamente, no son realmente muchos herramientas modernas relacionadas con el procesamiento de C código fuente de trabajo / ++.

En este sentido, la falta de compatibilidad con C ++, en realidad puede significar que usted puede tener que subir con sus propias herramientas para hacer cosas específicas. Entiendo perfectamente el razonamiento detrás de favorecer C en C ++ para algunas plataformas, entornos y proyectos, pero todavía C ++ compatibilidad general simplifica el diseño del proyecto en el largo plazo, y lo más importante:. proporciona opciones

Además, hay muchos proyectos de C que eventualmente se vuelven tan grandes que realmente se pueden beneficiar de las capacidades de C ++ 's como por ejemplo la mejora de suport para la abstracción y la encapsulación usando clases con modificadores de acceso.

mira el Linux (kernel) o gcc proyectos por ejemplo, ambos de los cuales son básicamente "C sólo", todavía existen discusiones regularmente en ambas comunidades de desarrolladores acerca de las posibles ventajas de cambiar a C ++.

Y, de hecho, no hay actualmente un esfuerzo gcc en curso ( en el árbol FSF!) Al puerto de las fuentes de GCC en C válida ++ sintaxis (véase: gcc-en-CXX para más detalles), de modo que un compilador de C ++ se puede utilizar para compilar el código fuente.

Esto fue básicamente iniciado por un pirata informático gcc largo plazo:. Ian Taylor Lanza

En un principio, esto es sólo destinado a proporcionar una mejor comprobación de errores, así como una mejor compatibilidad (es decir, una vez que se haya completado este paso, significa que usted no necesariamente tiene que tener un compilador C para compilar gcc, se puede también sólo tiene que utilizar un compilador de C ++, si quieres pasar a ser 'sólo' un desarrollador de C ++, y eso es lo que tienes de todos modos).

Pero con el tiempo, esta rama está destinado a fomentar la migración hacia C ++ como el lenguaje de implementación de gcc, que es un paso realmente revolucionaria -. Un cambio de paradigma que está siendo percibido críticamente por aquellas personas FSF

Por otra parte, es obvio que la severidad con gcc ya está limitada por su estructura interna, y que cualquier cosa que al menos ayuda a mejorar esta situación, se debe aplaudir: empezar contribuir al proyecto GCC es innecesariamente complicado y tedioso, sobre todo debido a la compleja estructura interna, que ya está a comenzaron a emular muchas de las características de nivel más alto en C ++ usando macros y extensiones específicas gcc.

Preparación de la base de código de gcc para un interruptor de final de C ++ es lo más lógico que hacer (no importa cuando se hace realmente, sin embargo!), Y que en realidad se requiere con el fin de seguir siendo competitivos, interesante y sencilla, simplemente relevante , esto se aplica, en particular, debido a los esfuerzos muy prometedores, como llvm, que no aportan todo esto, hay cosas, la complejidad con ellos.

Si bien la escritura de software muy complejo en C es a menudo posible, por supuesto, se hace innecesariamente complicado hacerlo, muchos proyectos han crecido más sencillo simplemente C hace mucho tiempo. Esto no quiere decir que el C ya no es relevante, sino todo lo contrario. Sin embargo, dada una cierta base y la complejidad del código, C, simplemente no es necesariamente la herramienta ideal para el trabajo.

De hecho, incluso se podría argumentar que C ++ no es necesariamente el lenguaje ideal para ciertos proyectos, pero siempre y cuando una lengua nativa soporta encapsulación y proporciona medios para hacer cumplir estas abstracciones, las personas pueden evitar estas limitaciones.

Sólo porque es obviamente posible escribir programas muy complejos en los idiomas de nivel muy bajo, no significa que debemos necesariamente es así, o que lo que realmente es eficaz en el primer lugar.

Estoy hablando aquí de un software complejo con cientos de miles de líneas de código, con una vida útil de varias décadas. En tal escenario, Las opciones son cada vez más importante.

No, cuestión de gustos. Odio a emitir punteros void, estorba el código por no mucho beneficio.

char * p = (char *)malloc(100);

vs

char * p = malloc(100);

y cuando escribo un módulo de biblioteca C "orientado a objetos", me gusta mucho usar el 'esto' como mi puntero del objeto y ya que es un C palabra clave ++ no sería compilar en C ++ (es intencional como este tipo de módulos son sin sentido en C ++ dado que existen como tales en stl y bibliotecas).

¿Por qué se ve poco beneficio? Es bastante fácil de hacer y que sabe cómo va a querer usar el código en el futuro.

No, siendo compilables por C ++ no es una interpretación común de la portátil. Tratar con código muy viejo, K & R declaraciones de estilo son muy portátiles, pero no pueden ser compilados en C ++.

Como ya se ha señalado, es posible que desee utilizar las opciones de C99. Sin embargo, me gustaría sugerir tiene en cuenta todos los usuarios de destino y asegurarse de que pueden hacer uso de las mejoras. No sólo tiene que utilizar matrices de longitud variable, etc., ya que tiene la libertad pero sólo si realmente justificadas.

Sí, es una buena cosa para mantener la compatibilidad C ++ tanto como sea posible - que otras personas pueden tener una buena razón por la que necesita para compilar el código C como C ++. Por ejemplo, si quieren incluirlo en una aplicación MFC que tendrían que construir C llana en una DLL o biblioteca independiente en lugar de sólo ser capaz de incluir su código en un solo proyecto.

También está el argumento de que la ejecución de un compilador de C ++ modo puede recoger a errores sutiles, dependiendo del compilador, si se aplica diferentes optimizaciones.

Que yo sepa todo el código en el texto clásico El lenguaje de programación C, Segunda edición puede ser compilado utilizando un estándar de compiladores de C ++ como GCC (g ++). Si el código C es hasta los estándares seguidos en ese texto clásico, entonces lo suficientemente bueno y que está listo para compilar el código C utilizando un compilador de C ++.

Tome el ejemplo de código fuente del núcleo de Linux que está escrito principalmente en C con un poco de código en línea ensamblador, es una pesadilla compilar el código del núcleo Linux con un compilador de C ++, debido a menos posible razón de que 'nuevo' está siendo utilizado como una nombre de la variable en el código del kernel Linux, donde como C ++ no permite el uso de 'nuevo' como nombre de variable. Sólo estoy dando un ejemplo aquí. Recuerde que el núcleo de Linux es portátil y compila y funciona muy bien en Intel, PPC, arquitecturas SPARC etc. Esto es sólo para ilustrar que la portabilidad no tener diferentes significados en el mundo del software. Si desea compilar código C utilizando un compilador de C ++, que está migrando su base de código de C a C ++. Lo veo como dos lenguajes de programación diferentes para la razón más obvia de que los programadores de C no le gusta mucho C ++. Pero me gusta tanto de ellos y lo uso tanto de ellos mucho. Su código C es portátil, pero debe asegurarse de que siga las técnicas estándar para tener su código C ++ portátil, mientras que la migración del código C a código C ++. Siga leyendo para ver de donde se obtendría las técnicas estándar.

Hay que tener mucho cuidado portar el código C para el código C ++ y la siguiente pregunta que me pregunto es, ¿por qué se molestan en hacerlo si alguna pieza de código C es portátil y funcionando bien sin ningún problema? No puedo aceptar managebility, de nuevo el núcleo de Linux una fuente de gran código en C se está manejando muy bien.

Siempre consulte los dos lenguajes de programación C y C ++ como diferentes lenguajes de programación, C ++, aunque es compatible con C & su idea básica es apoyar siempre para ese idioma maravilloso para compatibilidad con versiones anteriores. Si usted no está buscando en estos dos idiomas como diferentes herramientas, a continuación, usted se cae en la tierra de populares, fea C / C ++ guerras de lenguaje de programación y que se haga sucio.

Utilice las siguientes reglas al elegir la portabilidad:

a) ¿Su código (C o C ++) necesitan ser compilados en diferentes arquitecturas posiblemente utilizando compiladores nativos de C / C ++? b) hacer un estudio de los compiladores de C / C ++ en las diferentes arquitecturas que desea ejecutar su programa y plan para portar código. Invertir tiempo en esto. c) En la medida de lo posible tratar de proporcionar una capa limpia de la separación entre el código C & código C ++. Si el código C es portátil, sólo tiene que escribir encapsulamiento en C ++ en torno a que el código C portátil de nuevo usando C ++ portátil técnicas de codificación.

A su vez a algunos buenos libros de C ++ en la forma de escribir código C ++ portátil. Yo personalmente recomiendo el C ++ lenguaje de programación por el propio Bjarne Stroustrup, eficaz C ++ serie de Scott Meyers y artículos de divulgación DDJ que hay en www.ddj.com.

PS: Linux kernel ejemplo en mi post es simplemente para ilustrar que la portabilidad no significa diferentes significados en la programación de software y no critica que el kernel de Linux está escrito en C y no en C ++.

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