que - estructura general de un programa en lenguaje c
¿Cuáles son las principales diferencias entre ANSI C y K & R C? (11)
El artículo de Wikipedia sobre ANSI C dice:
Uno de los objetivos del proceso de estandarización de ANSI C fue producir un superconjunto de K & R C (el primer estándar publicado), que incorpora muchas de las características no oficiales introducidas posteriormente. Sin embargo, el comité de estándares también incluyó varias características nuevas, como prototipos de función (tomados del lenguaje de programación C ++) y un preprocesador más capaz. La sintaxis para declaraciones de parámetros también se cambió para reflejar el estilo C ++.
Eso me hace pensar que hay diferencias. Sin embargo, no vi una comparación entre K & R C y ANSI C. ¿Existe tal documento? Si no, ¿cuáles son las principales diferencias?
EDITAR: Creo que el libro de K & R dice "ANSI C" en la portada. Al menos creo que la versión que tengo en casa lo hace. Entonces quizás ya no hay diferencia?
Hay algunas diferencias menores, pero creo que las ediciones posteriores de K & R son para ANSI C, por lo que ya no hay diferencia real.
"C Classic" por falta de mejores términos tenía una forma ligeramente diferente de definir funciones, es decir,
int f( p, q, r )
int p, float q, double r;
{
// Code goes here
}
Creo que la otra diferencia fueron los prototipos de funciones. Los prototipos no tenían que - de hecho no podían - tomar una lista de argumentos o tipos. En ANSI C lo hacen.
La mayor diferencia individual, creo, es la creación de prototipos de funciones y la sintaxis para describir los tipos de argumentos de función.
Los prototipos de funciones fueron el cambio más obvio entre K & R C y C89, pero hubo muchos otros. También se realizó una gran cantidad de trabajo importante para estandarizar la biblioteca C. Aunque la biblioteca C estándar era una codificación de la práctica existente, codificó múltiples prácticas existentes, lo que lo hizo más difícil. El libro de PJ Plauger, The Standard C Library , es una gran referencia, y también cuenta algunos de los detalles detrás de escena de por qué la biblioteca terminó como lo hizo.
El estándar C de ANSI / ISO es muy similar a K & R C en la mayoría de los sentidos. Se pretendía que la mayoría de los códigos C existentes se basaran en compiladores ANSI sin muchos cambios. Crucialmente, sin embargo, en la era preestandarizada, la semántica del lenguaje estaba abierta a la interpretación de cada proveedor del compilador. ANSI C trajo una descripción común de la semántica del lenguaje que coloca a todos los compiladores en pie de igualdad. Es fácil dar esto por sentado ahora, unos 20 años después, pero este fue un logro significativo.
En su mayor parte, si no tiene una base de código C preestablecida para mantener, debería alegrarse de no tener que preocuparse por ello. Si lo haces, o peor aún, si tratas de llevar un viejo programa a estándares más modernos, entonces tienes mis simpatías.
Otra diferencia es que los tipos de retorno de función y los tipos de parámetros no necesitan ser definidos. Se supondría que eran enteros.
f(x)
{
return x + 1;
}
y
int f(x)
int x;
{
return x + 1;
}
Son identicos.
- PROTOTIPO DE FUNCIÓN: ANSI C adopta la técnica de prototipo de función c ++ donde la definición y declaración de funciones incluyen nombres de funciones, argumentos t, tipos de datos y tipos de datos de retorno. Prototipo de función habilita los ccompilers ANSI para verificar la función en el programa de usuario que pasa el número inválido de argumento o tipos de datos de argumentos incompatibles. Esto soluciona una debilidad importante de los compiladores K & R C: la llamada no válida en el programa de usuario a menudo pasa la compilación pero hace que el programa se bloquee cuando se ejecutan
- prototipo de función.
- Calificadores constantes y volátiles.
- amplio soporte de personajes e internacionalización.
- Permitir que el puntero de función se use sin desreferenciación.
La diferencia es:
- Prototipo
- amplio soporte de personajes e internacionalización
- Soporte para palabras clave const y volátiles
- Permitir que los punteros de función se utilicen como desreferenciación
Puede haber confusión aquí acerca de lo que es "K & R C". El término se refiere al lenguaje tal como se documentó en la primera edición de "The C Programming Language". A grandes rasgos: el lenguaje de entrada del compilador de Bell Labs C alrededor de 1978.
Kernighan y Ritchie estuvieron involucrados en el proceso de estandarización de ANSI. El dialecto "ANSI C" reemplazado por "K & R C" y las ediciones subsecuentes de "The C Programming Language" adoptan las convenciones de ANSI. "K & R C" es un "idioma inactivo", excepto en la medida en que algunos compiladores sigan aceptando el código heredado.
Las principales diferencias entre ANSI C y K & R C son las siguientes:
- prototipado de funciones
- soporte de los clasificadores de tipos de datos const y volátiles
- admite caracteres anchos e internacionalización
- Permitir que los punteros de función se utilicen sin desreferenciar
ANSI C adopta la técnica de prototipo de función c ++ donde la definición y declaración de funciones incluyen nombres de funciones, tipos de datos de argumentos y tipos de datos de valor de retorno. El prototipo de función habilita el compilador ANSI C para verificar las llamadas a funciones en programas de usuario que pasan números inválidos de argumentos o tipos de datos de argumentos incompatibles. Estos arreglan la debilidad principal del compilador K & R C.
Ejemplo: declarar una función foo y requiere que foo tome dos argumentos
unsigned long foo (char* fmt, double data)
{
/*body of foo */
}
Una diferencia importante que nadie ha mencionado hasta ahora es que antes de ANSI, C se definía en gran parte por precedente en lugar de especificación; en los casos donde ciertas operaciones tendrían consecuencias predecibles en algunas plataformas pero no en otras (por ejemplo, utilizando operadores relacionales en dos punteros no relacionados), el precedente favoreció fuertemente que las garantías de plataforma estuvieran disponibles para el programador. Por ejemplo:
En las plataformas que definen una clasificación natural entre todos los apuntadores para todos los objetos, se podría confiar en la aplicación de los operadores relacionales a punteros arbitrarios para obtener esa clasificación.
En plataformas donde el medio natural de probar si un puntero es "mayor que" otro nunca tiene ningún efecto secundario que no sea arrojar un valor verdadero o falso, la aplicación de los operadores relacionales a punteros arbitrarios también podría depender de no tener ningún lado -efectos que no sean arrojar un valor verdadero o falso.
En las plataformas donde dos o más tipos de enteros compartían el mismo tamaño y representación, se podía confiar en un puntero a cualquier tipo de entero para leer o escribir información de cualquier otro tipo con la misma representación.
En las plataformas complementarias donde los desbordamientos de enteros se envuelven naturalmente silenciosamente, se puede confiar en que una operación que involucre valores sin signo menores que "int" se comporte como si el valor no estuviera firmado en casos donde el resultado sería entre INT_MAX + 1u y UINT_MAX y no se promocionó a un tipo más grande, ni se utilizó como el operando de la izquierda de
>>
, ni tampoco operando de/
,%
o cualquier operador de comparación. Dicho sea de paso, la justificación del Estándar le da a esto como una de las razones por las cuales los pequeños tipos sin firmar promueven la firma .
Antes de C89, no estaba claro hasta qué punto los compiladores para las plataformas donde las suposiciones anteriores no contendrían naturalmente se podrían esperar para mantener esas suposiciones de todos modos, pero había pocas dudas de que los compiladores de plataformas que pudieran mantener estos supuestos fueran fáciles y baratas. debería hacerlo. Los autores del estándar C89 no se molestaron en decirlo expresamente porque:
Los compiladores cuyos escritores no eran deliberadamente obtusos continuarían haciendo tales cosas cuando sea práctico sin necesidad de que se les diga (la lógica dada para promover la firma de pequeños valores sin firmar refuerza fuertemente esta visión).
El estándar solo requería implementaciones para ejecutar un programa posiblemente artificial sin desbordamiento de pila, y reconoció que una implementación obtusa podía tratar cualquier otro programa como invocando el comportamiento indefinido pero no creía que valiera la pena preocuparse por la escritura obtusa de escritores de compiladores implementaciones que eran "conformes" pero inútiles.
Si bien "C89" fue interpretado contemporáneamente como "el lenguaje definido por C89, más las características y garantías adicionales que brinde la plataforma", los autores de gcc han estado impulsando una interpretación que excluye cualquier característica y garantía más allá de lo exigido por C89.
A pesar de todos los reclamos al contario, K & R era y es bastante capaz de proporcionar cualquier tipo de cosas desde abajo hasta cerca del hardware. El problema ahora es encontrar un compilador (preferiblemente gratuito) que pueda dar una compilación limpia en un par de millones de líneas de K & R C sin tener que meterse con él. Y ejecutar algo así como un procesador AMD multi core.
Por lo que puedo ver, habiendo examinado la fuente de la serie GCC 4.xx, no existe un truco simple para reactivar la funcionalidad de retardo -tradicional y -cpp-tradicional a su estado de trabajo anterior sin más esfuerzo de lo que estoy dispuesto a hacer. poner. Y más simple para construir un compilador pre-ansi de K & R desde cero.