¿Es necesario seguir el estándar, tomar el estándar C para el caso?

17

Hay algunas personas muy experimentadas en Stack Overflow que siempre hablan sobre el estándar C. Parece que a las personas no les gustan las soluciones no portátiles, incluso si trabajan para mí. Ok, entiendo que el estándar debe seguirse, pero ¿no pone grilletes a la creatividad del programador?

¿Cuáles son los beneficios concretos que se obtienen al seguir un estándar? Especialmente porque los compiladores pueden implementar el estándar de forma ligeramente diferente.

0decimal0
fuente
77
¿Podría aclarar qué quiere decir con "el estándar"? ¿Te refieres a no realizar comportamientos que no están definidos por el estándar? ¿O no está usando extensiones / características del compilador? O convenciones de estilo?
ikh
1
@ikh Él está tomando los estándares ISO C (C90, C99, C11).
Aseem Bansal
9
Es lo mismo que decir que escribir o hablar en inglés, usando gramática y vocabulario en inglés, pone grilletes a tu creatividad. Claro, las personas pueden hacer cosas maravillosas rompiendo las reglas, a costa de la coherencia, pero puedes escribir millones de libros creativos sin dejar de cumplir el "estándar" del inglés.
Avner Shahar-Kashtan
¿Puedes agregar un ejemplo de "Parece que a las personas no les gustan las soluciones no portátiles, incluso si trabajan para mí"?
Bћовић
1
@PHIfounder Solo para abordar ese último caso, puede omitir el retorno de main, implícitamente devuelve 0 :)
Daniel Gratzer

Respuestas:

45

Hay algunas razones por las cuales apegarse al estándar es algo bueno.

  1. Estar encerrado en un compilador apesta mucho. Estás completamente a merced de un grupo de desarrolladores con su propia agenda. Obviamente, no están tratando de atraparte ni nada, pero si tu compilador comienza a retrasarse en optimizaciones, nuevas funciones, correcciones de seguridad, etc., es una lástima; Estas atorado. En casos extremos, algunas empresas tienen que comenzar a parchar cualquier herramienta de la que se hayan hecho dependientes. Esta es una gran pérdida de dinero y tiempo cuando hay otras herramientas de trabajo disponibles.

  2. Estar encerrado en una plataforma apesta más. Si está impulsando el software en Linux y desea cambiar a Windows porque se da cuenta de que su mercado realmente está allí, tendrá que cambiar muchísimo cada pirateo no portátil que tenga en su código para jugar bien tanto con GCC como con MSVC. Si tienes varias piezas de tu diseño principal basadas en algo así, ¡buena suerte!

  3. Los cambios incompatibles hacia atrás son los más difíciles. El estándar nunca romperá su código (Ignorar python). Sin embargo, algún escritor compilador aleatorio podría decidir que realmente este complemento específico de implementación no vale la pena y lo descarta. Si confías en él, entonces estás atrapado en cualquier versión antigua y desactualizada en la que estaba por última vez.

Entonces, el mensaje principal aquí, apegarse al estándar lo hace más flexible . Tienes un idioma más limitado, pero tienes más

  • Bibliotecas
  • Soporte (la gente conoce el estándar, no todos los intrincados trucos específicos del compilador)
  • Plataformas disponibles
  • Herramientas maduras
  • Seguridad (pruebas futuras)

Es un equilibrio delicado, pero ignorar completamente el estándar es definitivamente un error. Tiendo a organizar mi código C para confiar en abstracciones que podrían implementarse de una manera no portátil, pero que puedo portar de forma transparente sin cambiar todo lo que depende de la abstracción.

Daniel Gratzer
fuente
+1 bastante justo :), gracias ... Estaba seriamente confundido sobre la forma en que los compiladores se desviaron ligeramente de los estándares y me hicieron sentir escéptico sobre seguirlo estrictamente, necesitaba saber los pros y los contras de eso y claramente los identificaste.
0decimal0
66
El comportamiento indefinido probablemente también apesta bastante. Con c es bastante fácil aventurarse en UB si no sigue de cerca el estándar.
CodesInChaos
@CodesInChaos De acuerdo, el comportamiento indefinido es excelente por un lado, ya que permite algunas optimizaciones locas, pero por otro lado lo depura ...
Daniel Gratzer
6

El estándar es una especie de "contrato" entre usted y su compilador que define el significado de sus programas. Como programadores, a menudo tenemos un cierto modelo mental de cómo funciona el lenguaje, y este modelo mental a menudo está en desacuerdo con el estándar. (Por ejemplo, los programadores de C a menudo piensan en un puntero como "un número entero que denota una dirección de memoria", y por lo tanto suponen que es seguro realizar cualquier aritmética / conversiones / manipulaciones en punteros que uno podría realizar con un número entero que denota una memoria dirección. Esta suposición no está de acuerdo con el estándar; en realidad impone restricciones muy estrictas sobre lo que puede hacer con los punteros).

Entonces, ¿cuál es la ventaja de seguir el estándar, en lugar de su propio modelo mental?

En pocas palabras, es que el estándar es correcto y su propio modelo mental está equivocado. Su modelo mental suele ser una vista simplificada de cómo funcionan las cosas en su propio sistema, en casos comunes, con todas las optimizaciones del compilador desactivadas; Los proveedores de compiladores generalmente no se esfuerzan por cumplir con él, especialmente cuando se trata de optimizaciones. (Si no retrasa su finalización del contrato, no puede esperar ningún comportamiento específico del compilador: basura, basura).

Parece que a las personas no les gustan las soluciones no portátiles, incluso si trabajan para mí.

Podría ser mejor decir, "incluso si parecen funcionar para mí". A menos que su compilador documente específicamente que un comportamiento dado funcionará (es decir: a menos que esté usando un estándar enriquecido, que consiste en la documentación estándar más adecuada del compilador), no sabe que realmente funciona o que es realmente confiable. Por ejemplo, el desbordamiento de enteros con signo suele dar lugar a muchos sistemas (por INT_MAX+1lo general , lo es INT_MIN), excepto que los compiladores "saben" que la aritmética de enteros con signo nunca se desborda en un programa C (correcto) y, a menudo, realizan optimizaciones muy sorprendentes basadas en esto " conocimiento".

ruakh
fuente
1
Puede compilar con -fwrapv, y luego está usando un lenguaje no estándar ligeramente diferente donde la aritmética de enteros con signo siempre se ajusta.
user253751
@immibis: cuando se escribió C89, de acuerdo con su documento de justificación, la mayoría de los compiladores contemporáneos definieron la semántica de envoltura silenciosa para el desbordamiento de enteros. En muchos casos, tener algunos tipos de garantías sobre lo que sucede en caso de desbordamiento de enteros puede permitir que el código sea más eficiente de lo que sería posible sin tales garantías, especialmente si las garantías no llegan a exigir un comportamiento de ajuste preciso [precisa el comportamiento de ajuste podría emularse usando matemáticas sin signo, pero la semántica, que es más flexible pero adecuada para cumplir con los requisitos, puede permitir un código más eficiente].
supercat
@immibis: Es una lástima que los revisionistas hayan podido convencer a la gente de que los comportamientos que se implementaron casi por unanimidad entre los compiladores para ciertas plataformas (o en algunos casos 100% por unanimidad) nunca han sido "estándar" en tales plataformas, ya que en muchos casos el la pérdida de eficiencia resultante de tener que evitar tales comportamientos no será recuperada por ninguna "optimización" que un compilador pudo lograr al revocarla.
supercat
4

Entiendo que el estándar debe seguirse, pero ¿no pone grilletes a la creatividad del programador? Todavía hay algunas diferencias en la forma en que los diferentes compiladores siguen los estándares. Puedo, por ejemplo, escribir un código que funcione, muy bueno en rendimiento y velocidad, es decir, todo lo que importa, pero aún así no necesariamente sigue estrictamente los estándares.

No. El estándar dice lo que está permitido hacer. Si no se especifica, se encuentra en un territorio de comportamiento indefinido, y luego todas las apuestas están apagadas: el programa es libre de hacer cualquier cosa.


Como mencionó un ejemplo específico de void main() vs int main(), puedo mejorar mi respuesta.

void main()No es una declaración estándar de la función principal. Puede funcionar en algunos compiladores a través de extensiones, pero depende de la implementación. Incluso si funciona, debe verificar si hace lo que quiere. El problema es que los desarrolladores del compilador pueden decidir eliminarvoid main() con la próxima versión del compilador, rompiendo su aplicación.

Por otro lado, el estándar define claramente la firma de main como int main() y le dice lo que debe hacer.


Por otro lado, hay cosas que no están definidas en el estándar. Luego, puede aplicarse otro estándar (como, por ejemplo, POSIX). El mejor ejemplo puede ser con la implementación de subprocesos en c ++ 03, ya que los programas estándar de c ++ 03 tenían 1 subproceso. En ese caso, se ve obligado a utilizar la biblioteca dependiente de la plataforma, o algo así como impulsar .

BЈовић
fuente
44
Todo lo que hace un compilador que no es estándar no es un comportamiento indefinido, las extensiones del compilador están bien definidas en el sentido de que son deterministas y deliberadas. UB no lo es.
Daniel Gratzer
@jozefg La forma en que se le preguntó: es obvio que el OP pensó en la forma de implementación de UB. Por ejemplo, los hilos no se definieron en c ++ 03.
Bћовић
1
@deworde: El comentario fue eliminado de la respuesta.
Kevin
@jozefg Si un compilador en particular siempre envuelve enteros con signo, podría considerarse una extensión de lenguaje no documentada. (Por supuesto, ser indocumentado significa que no tiene garantías de que no
eliminen
-6

No siga las reglas SI su proyecto se trata de proyectos especiales, por ejemplo, un proyecto de gobierno o uno militar, pero debe seguir las reglas SI está hablando de un proyecto de código abierto o grande con un equipo distribuido.

Desconocido
fuente
2
sin una explicación, esta respuesta puede volverse inútil en caso de que alguien más publique una opinión opuesta. Por ejemplo, si alguien publica un reclamo como "sigue las reglas SI tu proyecto se trata de proyectos especiales, por ejemplo, un proyecto de gobierno o uno del ejército, pero no necesitas seguir las reglas SI estás hablando de un código abierto ..." , ¿cómo podría esta respuesta ayudar al lector a elegir dos opiniones opuestas? Considere editarlo en una mejor forma
mosquito
2
Desconocido: te sorprendería saber cuántos estándares hay en los proyectos del gobierno ...
Deer Hunter