¿C está fuertemente tipado?

88

Para citar Wikipedia :

Dos lenguajes de uso común que admiten muchos tipos de conversión implícita son C y C ++, y a veces se afirma que se trata de lenguajes de tipo débil. Sin embargo, otros argumentan que estos lenguajes imponen suficientes restricciones sobre cómo se pueden mezclar operandos de diferentes tipos, que los dos deben considerarse como lenguajes fuertemente tipados.

¿Existe una respuesta más definitiva?

Sydius
fuente
188
Para un programador de C, escribir fuerte significa presionar las teclas con más fuerza.
Dan Dyer
2
C está en el lado débil del continuo de mecanografía. Pero hay suficientes elementos en ambos lados que puedes discutir de cualquier manera. Mientras lo hace, también puede preguntar (vi o emacs, netbeans o eclipse, etc.)
Cervo
4
La situación en Wikipedia era tan mala que me sentí obligado a editar varias páginas de Wikipedia. Quizás las cosas estén un poco mejor ahora. Tal vez.
Norman Ramsey
40
Re: Comentario de Dan (para dar crédito a lo que se debe) El libro de Peter van der Linden "Programación experta en C" contiene la siguiente línea: "Hasta el día de hoy, muchos programadores en C creen que 'escribir con precisión solo significa golpear más fuerte el teclado".
Alexandros Gezerlis
Muy buena pregunta !!!
Destructor

Respuestas:

154

"Fuertemente tipado" y "débilmente tipado" son términos que no tienen un significado técnico ampliamente aceptado. Los términos que tienen un significado bien definido son

  • Tipado dinámicamente significa que los tipos se adjuntan a los valores en tiempo de ejecución y un intento de mezclar valores de diferentes tipos puede causar un "error de tipo en tiempo de ejecución". Por ejemplo, si en Scheme intenta agregar uno a verdadero escribiendo, (+ 1 #t)esto provocará un error. Se encuentra con el error solo si intenta ejecutar el código infractor.

  • Tipado estático significa que los tipos se comprueban en tiempo de compilación, y el compilador rechaza un programa que no tiene un tipo estático. Por ejemplo, si en ML intenta agregar uno a verdadero escribiendo 1 + true, el programa será rechazado con un mensaje de error (probablemente críptico). Siempre obtiene el error incluso si el código nunca se ejecutará.

Diferentes personas prefieren diferentes sistemas según en parte cuánto valoran la flexibilidad y cuánto se preocupan por los errores de tiempo de ejecución.

A veces, "fuertemente tipado" se usa libremente para significar "tipado estáticamente", y "tipado débilmente" se usa incorrectamente para significar "tipado dinámicamente". Un mejor uso para el término "fuertemente tipado" es que "no se puede evitar o subvertir el sistema de tipos", mientras que "débilmente tipado" significa "hay lagunas en el sistema de tipos". Perversamente, la mayoría de los lenguajes con sistemas de tipos estáticos tienen lagunas, mientras que muchos lenguajes con sistemas de tipos dinámicos no tienen lagunas.

Ninguno de estos términos está relacionado de ninguna manera con el número de conversiones implícitas disponibles en un idioma.

Si desea hablar con precisión sobre lenguajes de programación, es mejor evitar los términos "tipado fuerte" y "tipado débil". Yo diría que C es un lenguaje que se escribe estáticamente pero que tiene muchas lagunas. Una laguna es que puede lanzar libremente cualquier tipo de puntero a cualquier otro tipo de puntero. También puede crear una laguna entre dos tipos de su elección al declarar una unión C que tiene dos miembros, uno para cada uno de los tipos en cuestión.

He escrito más sobre tipado estático y dinámico en why-interpreted-langs-are-most-ducktyped-while-compiled-have-strong-typing .

Norman Ramsey
fuente
2
¿De dónde sacaste las definiciones que sugieres para tipado fuerte / débil (la cosa de la escapatoria)?
Sydius
2
¿Por qué necesitaría un "vacío legal" en un entorno de escritura dinámica?
Chris Conway
4
@Sydius: De pasar gran parte de los últimos 20 años con personas que diseñan, construyen y analizan lenguajes de programación y sistemas de tipos. Ese es mi trabajo remunerado :-)
Norman Ramsey
@Chris: Nunca he visto un lenguaje escrito dinámicamente con 'escapatoria'. El uso común de laguna es trabajar con un sistema operativo o un sistema en tiempo de ejecución, por ejemplo, tomar una dirección sin formato y convertirla en un puntero a un valor de lenguaje de buen comportamiento. Podría hacer esto en un entorno dinámico, pero no conozco ningún intento.
Norman Ramsey
1
@NormanRamsey Creo que Chris se refería con su pregunta a:whereas "weakly typed" means "there are loopholes in the type system
Nir Alfasi
23

Es difícil clasificar cada idioma en "débil" o "fuerte", es más un continuo. Pero, en comparación con otros lenguajes, C tiene un tipo bastante fuerte. Cada objeto tiene un tipo en tiempo de compilación, y el compilador le hará saber (en voz alta) si está haciendo algo con un objeto que su tipo no le permite hacer. Por ejemplo, no puede llamar a funciones con los tipos de parámetros incorrectos, acceder a miembros de estructura / unión que no existen, etc.

Pero hay algunas debilidades. Una de las principales debilidades son los encasillamientos: esencialmente dicen que vas a estar jugando con los tipos de objetos, y el compilador debe estar en silencio (cuando pueda). void*también es otra debilidad: es un puntero genérico a un tipo desconocido, y cuando los usa, debe tener mucho cuidado de hacer lo correcto. El compilador no puede verificar estáticamente la mayoría de los usos de void*. void*también se puede convertir en un puntero a cualquier tipo sin una conversión (solo en C, no en C ++), que es otra debilidad.

Adam Rosenfield
fuente
Buena respuesta, aunque me molesta "encasillar ... y el compilador debería estar tranquilo". Un encasillado no es como apagar una advertencia, en realidad cambia la interpretación del valor al que se hace referencia.
Tall Jeff
15
Estás confundiendo "estático" y "fuerte" en relación con la escritura. Estos dos conceptos son independientes entre sí.
bendin
1
Dennis Richie (autor de C) llamó a C 'fuertemente tipado y débilmente verificado'
TimZaman
11

La literatura no es clara al respecto. Creo que la escritura fuerte no es sí / no, hay varios grados de escritura fuerte.

Un lenguaje de programación tiene una especificación de cómo ejecuta programas. A veces, no está claro cómo ejecutar con ciertos programas. Por ejemplo, programas que intentan restar una cadena de un número. O programas que dividen por cero. Hay varias formas de lidiar con estas condiciones. Algunos lenguajes tienen reglas para lidiar con estos errores (por ejemplo, lanzan una excepción). Otros idiomas simplemente no tienen reglas para lidiar con estas situaciones. Por lo general, esos lenguajes tienen sistemas de tipos para evitar la compilación de programas que conducen a un comportamiento no especificado. Y también existen lenguajes que tienen un comportamiento no especificado y no tienen un sistema de tipos para evitar estos errores en el momento de la compilación (si escribe un programa que tiene un comportamiento no especificado, podría lanzar los misiles).

Entonces:

Los lenguajes que especifican lo que sucede en tiempo de ejecución en todos los casos (como agregar un número a una cadena) se denominan tipados dinámicamente. Los lenguajes que impiden ejecutar programas con errores en tiempo de compilación se escriben estáticamente. Los lenguajes que no especifican lo que sucede y tampoco tienen un sistema de tipos para evitar errores se denominan de tipo débil.

Entonces, ¿Java está tipado estáticamente? Sí, porque su sistema de tipos no permite restar una cadena de un número. No, porque te permite dividir por cero. Puede evitar la división por cero en tiempo de compilación con un sistema de tipos. Por ejemplo, creando un tipo de número que no puede ser cero (por ejemplo, NonZeroInt) y solo permite dividir por números que tienen este tipo.

Entonces, ¿C está fuertemente tipado o débilmente tipado? C está fuertemente tipado porque el sistema de tipos no permite algunos errores de tipos. Pero está débilmente escrito en otros casos cuando no está definido lo que sucede (y el sistema de tipos no lo protege).

Jules
fuente
Me gusta que alinees lo dinámico y lo estático como formas de fuerte y débil. Sin embargo, no estoy seguro de entender su punto de que los sistemas de tipo estático dejan de dividir por cero. Si mi tipado estático intobtiene un valor del usuario o de los argumentos de la línea de comandos o de un archivo, ¡no hay nada que el compilador pueda hacer para evitar que sea un cero!
Rikki
1
Hay sistemas de tipos estáticos que evitan esto, pero la mayoría de los lenguajes se "escriben" débil o dinámicamente con respecto a la división por cero, porque es un comportamiento indefinido (C) o lanzan una excepción (Java).
Jules
11

Se considera que C tiene un tipo débil, porque puede convertir cualquier tipo a cualquier otro a través de una conversión, sin un error de compilación. Puede leer más sobre el problema aquí .

mipadi
fuente
2
wikipedia es engañoso aquí. C está fuertemente tipado, los tipos son muy válidos y el compilador dejará de funcionar si los malinterpreta, sin embargo, C también proporciona funciones para que usted lo omita. Compare con lenguajes como BCPL que solo tienen un tipo de 'byte'.
gbjbaanb
12
Un tipo de letra débil no significa que un idioma no tenga ningún tipo, solo significa que los tipos pueden ser coaccionados implícitamente de un tipo a otro. Compare con Python, un lenguaje fuertemente tipado en el que debe convertir explícitamente tipos con llamadas a funciones.
mipadi
¿Ser capaz de lanzar algo en C también contribuye a que sea un tipo débil? Tengo esta duda por siempre
Suraj Jain
8

C es más tipado que Javascript y menos tipado que Ada.

Yo diría que cae más en el lado fuertemente tipado del continuo. pero alguien más podría estar en desacuerdo (incluso si está equivocado).

¿Cómo es eso para definitivo?

Michael Burr
fuente
Fue una respuesta un tanto irónica. Pero profundice en lo incorrecto.
Michael Burr
1
Javascript está fuertemente tipado. Simplemente no está tipado estáticamente. Todas las verificaciones de tipo ocurren en tiempo de ejecución (dinámicas, no estáticas) pero ocurren y evitan que corrompa la memoria (un aspecto de la escritura segura).
bendin
5
Bueno, como indica la muy buena respuesta de Norm Ramsey, "tipado fuerte" y "tipado débil" no son términos particularmente bien definidos. Además, en la medida en que Javascript esté fuertemente tipado, algunos podrían creer que ("4" / ​​"2") siendo una expresión válida de Javascript podría indicar lo contrario.
Michael Burr
5

C se considera de tipo estático (no puede tener un cambio de variable de int a float). Una vez que se declara una variable, se bloquea de esa manera.

Pero se considera de tipo débil porque los tipos se pueden cambiar.

¿Qué es 0? '\ 0', FALSO, 0.0, etc.

en muchos idiomas no se puede decir IF (variable) porque las condiciones solo tomarán valores booleanos de expresiones booleanas. Estos se escriben con más rigor. Lo mismo se aplica al ir entre caracteres y números enteros.

Básicamente, c tiene dos tipos de datos simples principales, números enteros y números de coma flotante (aunque con varias precisiones). Todo lo demás booleanos, enumeraciones (no simples pero encaja), etc. se implementan como uno de esos. Incluso los caracteres son básicamente números enteros.

Compare con otros lenguajes donde hay tipos de cadenas, tipos de enumeración que solo se pueden asignar a los valores definidos, tipos booleanos donde solo se pueden usar expresiones que generan booleanos o verdadero / falso.

Pero se puede argumentar que en comparación con Perl C está fuertemente tipado. Así que es uno de esos argumentos famosos (vi vs emacs, linux vs windows, etc.). C # tiene un tipo más fuerte que C. Básicamente, puedes argumentar de cualquier manera. Y sus respuestas probablemente irán en ambos sentidos :) Además, algunos libros de texto / páginas web dirán que C tiene un tipo débil, y algunos dirán que C tiene un tipo fuerte. Si va a wikipedia, la entrada C dice "escritura parcialmente débil". Yo diría que en comparación con Python C tiene un tipo débil. Entonces Python / C #, C, Perl en el continuo.

Cervo
fuente
Explique su razonamiento de que Perl se escribe menos fuertemente que C.
user51568
imprimir "Prueba" + 0 # perl hará 0; $ var = "cadena"; $ var = 1; $ var = 123,4; ¿Qué tipo de variable es?
Cervo
En C char * test = "testing"; printf (prueba + 0); seguirá siendo una cadena, es solo que en C el índice cambiará si en lugar de cero uso un número. Todavía es bastante débil, pero un poco más fuerte que Perl. char * prueba; prueba = 0; prueba = 123,4; test = "c"; ... mi compilador genera errores
Cervo
el error dice que se requiere un yeso. Aún así, es un control de tipo un poco más fuerte que Perl, por lo que en el continuo debo decir que C está más fuertemente tipado que Perl. Todavía puede probar = (char *) y luego usar 0, 123.4, 'C', etc. Pero es un error simplemente hacerlo.
Cervo
4

Muchas buenas respuestas aquí. Quiero mencionar un punto importante de Real World Haskell :

Es útil saber que muchas comunidades lingüísticas tienen sus propias definiciones de “tipo fuerte”. No obstante, hablaremos brevemente y en términos amplios sobre la noción de fuerza en sistemas de tipos.

(recorte)

Los fuegos artificiales en torno a los sistemas de tipos tienen sus raíces en el inglés corriente, donde la gente atribuye nociones de valor a las palabras "débil" y "fuerte": normalmente pensamos en la fuerza como mejor que la debilidad. Muchos más programadores hablan un inglés sencillo que la jerga académica, y muy a menudo los académicos realmente están tirando ladrillos a cualquier tipo de sistema que no se adapte a sus gustos. El resultado es a menudo ese pasatiempo popular de Internet, una guerra de llamas.

Entonces, mire las respuestas sobre C y C ++, pero recuerde que 'fuerte' y 'débil' no se corresponden con 'bueno' y 'malo'.

Delgado
fuente
4

Según Dennis Ritchie ( creador de C ) y Brian Kernighan, C no es un lenguaje fuertemente tipado. Las siguientes líneas son del libro El lenguaje de programación C, página 3, párrafo 5

C no es un lenguaje fuertemente tipado, pero a medida que ha evolucionado, su verificación de tipos se ha fortalecido.

mightyWOZ
fuente
3

En mi opinión, C / C ++ están fuertemente tipados. El tipo de hacks que permiten convertir tipos (void *) existen debido a la cercanía de C a la máquina. En otras palabras, puede llamar a comandos de ensamblador desde Pascal y manipular punteros y Pascal todavía se considera un lenguaje fuertemente tipado. Puede llamar a ensamblador y ejecutables de C desde Java a través de JNI, pero no hace que Java tenga un tipo débil.

C simplemente tiene ensamblador "incrustado" en él con punteros en bruto y tal.

mannicken
fuente
3

El término fuertemente tipado no tiene una definición acordada. Por lo tanto, a menos que defina lo que quiere decir con "fuertemente tipado", es imposible responder a su pregunta.

En mi experiencia, los términos "fuertemente tipificado" y "débilmente tipificado" son utilizados exclusivamente por los trolls, porque su falta de definiciones les permite redefinirlos a mitad de la discusión para adaptarlos a su agenda. Aparte de iniciar flamewars, estos términos son bastante inútiles.

Es posible que también desee echar un vistazo a ¿Cuáles son los aspectos clave de un lenguaje fuertemente tipado? aquí en StackOverflow.

Jörg W Mittag
fuente
3
Estoy en desacuerdo. "Fuertemente tipado" significa que es posible determinar el tipo de datos de un valor, y solo se permiten operaciones apropiadas para ese tipo. Abordar "dinámicamente" y "estáticamente" cuándo se puede hacer esa determinación.
joel.neely
2
Se da cuenta de la ironía de tratar de refutar la afirmación de que no existe una definición acordada al introducir otra definición, ¿verdad?
Jörg W Mittag
1
@Jorg: No estoy intentando introducir otro; simplemente indicando el que se usa comúnmente en los círculos en los que me muevo.
joel.neely
1

Existe un continuo con múltiples avenidas paralelas entre "tipado débil" y "tipado fuerte", dos términos que ni siquiera están bien definidos.

C se escribe estáticamente , ya que el compilador sabe cuál es el tipo declarado de cada variable local y miembro de estructura.

Los lenguajes tipados dinámicamente aún pueden estar fuertemente tipados, si cada objeto tiene un tipo específico pero no hay forma de que el compilador conozca ese tipo.

yfeldblum
fuente
0

¿Cuál es el motivo de su consulta? La razón por la que pregunto es que se trata de una pequeña diferencia y su uso particular de "fuertemente tipado" podría necesitar más o menos aclaración. Definitivamente diría que Java y otros lenguajes tienen restricciones más estrictas en la conversación de tipo implícito.

BobbyShaftoe
fuente
Principalmente curiosidad, pero estoy solicitando un puesto C y quería saber en caso de que me interroguen al respecto.
Sydius
Entonces, probablemente la respuesta más larga que da los matices de lo que "fuertemente tipado" es el mejor enfoque en lugar de simplemente decir "sí" o "no".
BobbyShaftoe
0

Es difícil dar una respuesta concreta cuando no existe una definición concreta de "fuertemente tipado". Yo diría que C está fuertemente tipado en el sentido de que cada variable y cada expresión tiene un tipo pero débilmente tipado que le permite cambiar tipos usando conversiones y reinterpretar la representación de un tipo como otro.

Robert Gamble
fuente
Hay una def. Oficial. para fuertemente tipado. Dice que un sys. es ST cuando se garantiza que no hay error de tipo de tiempo de ejecución. Ejemplo: ML, Haskell. Esto es útil para que el sistema omita las etiquetas de tipo dentro de los objetos y, sin embargo, aplique los operadores en los tipos correctos. Porque sabemos antes de la ejecución que no hay necesidad de etiquetas en los objetos. Debido a que C ha emitido y tiene acceso de puntero a memo arbitrario, C no es st
alinsoar
0

Yo diría que C está tan fuertemente tipado como dicta su compilador / plataforma. Por ejemplo, si está construyendo sobre una plataforma estricta, es probable que la eliminación de referencias a un puntero de tipo juego de palabras se rompa:

void m_free(void **p)
{
        if (*p != NULL) {
                free(*p);
                *p = NULL;
        }
}

....
char *str = strdup("foo");
m_free((void **) &foo);

Ahora, si le dice al compilador que omita el alias estricto, no sería un problema, pero no sería muy portátil. Entonces, en ese sentido, empujar los límites del lenguaje es posible pero probablemente no sea la mejor idea. Eso va un paso más allá del casting típico, es decir, lanzar int tan largo y realmente muestra uno de los posibles escollos del vacío.

Entonces, yo diría que C es básicamente un tipo estricto, pero sus diversos compiladores suponen que el programador sabe más y permite cierta flexibilidad. Esto realmente depende del compilador, algunos no se darían cuenta de ese potencial oops. Entonces, en ese sentido, el compilador elegido realmente juega un papel al responder la pregunta. Lo que es correcto a menudo difiere de lo que su compilador le permitirá salirse con la suya.

Tim Post
fuente
0

c tiene un tipo débil, b no tiene tipo.

plan9 ensamblador
fuente
Esta respuesta es excesivamente corta dada la pregunta.
Keith Pinson
-1

No muy tipado.

Considere lo que le dice el siguiente prototipo de función sobre los tipos de datos de los argumentos:

void func (int n, char ch, ...);

Nada. Por lo tanto, sugiero que aquí no se aplique el tipo fuerte.

joel.neely
fuente
¿Eh? Te dice que hay un int, seguido de un char, seguido de cualquier número de argumentos de cualquier tipo. Eso no es "nada".
Lawrence Dol
El ... no le dice nada sobre los tipos de argumentos que se pasan. Es cierto que el tipo de función en sí es conocido. Eso es lo que dijo Software Monkey.
Johannes Schaub - litb
Esos "cualquier número de argumentos de cualquier tipo" es de lo que estoy hablando. Una cadena es tan fuerte como su eslabón más débil.
joel.neely
-3

Yo diría que es fuertemente tipos, ya que cada expresión tiene un tipo que no es función de su valor; ei se puede conocer antes del tiempo de ejecución.

OTOH No estoy seguro de que sea la descripción correcta de fuertemente tipado. La única afirmación más sólida que puedo ver como razón para hacer un lenguaje sería la garantía de que no se puede subvertir el sistema de tipos en tiempo de ejecución mediante la reinterpretación de tipos de conversión, uniones, llamadas a otros idiomas, punteros, lenguaje ensamblador, etc. Idiomas como este existen, pero están tan paralizados que no parecen ser de mucho interés para los programadores fuera del ámbito académico y de alta seguridad. Como lo señaló alguien, para hacer eso realmente bien, comienza a necesitar tener tipos como nonZeroInty otras cosas. ¡Qué asco!

BCS
fuente
3
¿Qué no es? ¿Mi definición de fuertemente tipado o C?
BCS