tipos switch lenguaje funciones ejemplos completo comandos codigos c compiler-construction functional-programming type-inference

lenguaje - switch en c



¿Sería posible agregar inferencia tipo al lenguaje C? (6)

Digamos que creamos una reimplementación de C, con la única diferencia de que los tipos se deducen. Las clases de almacenamiento y los modificadores aún tendrían que darse (const, static, restrict, etc.) y restringiremos nuestra atención a los programas de C de un solo archivo por el momento. ¿Podría hacerse? ¿Cuáles son los principales impedimentos?

Algunas reflexiones sobre lo que podría causar problemas con la inferencia de tipos

  • las estructuras con el mismo nombre de campo necesitarían ser desambiguadas manualmente
  • lo mismo para las uniones con los mismos nombres de campo
  • los moldes probablemente necesitarían una anotación "de", algo así como

    var i = (uint32_t -> uint64_t) *some_pointer;

Estos problemas requerirían un poco de anotación para el usuario, pero no deberían ser demasiado engorrosos. ¿Existe algún problema mortal que expulse esta idea del agua?

Editar: para aclarar, no estoy hablando de agregar genéricos o polimorfismo paramétrico, solo escriba inferencia para los tipos de C existentes.

Edición 2014: cualquier persona interesada en este concepto puede querer mirar en Rust


Algunas situaciones en las que, creo, los tipos inferidos no se pueden usar:

  • los punteros necesitan un tipo definido
  • matrices necesitan un tipo definido
  • los parámetros de función necesitan un tipo

Creo que podría funcionar en algunos casos, principalmente variables locales simples.

Incluso algo tan simple como calcular una suma de comprobación necesita un tipo definido

crc8 = 0x00; /* 8 bits; cf uint8_t crc8 = 0; */ crc32 = 0x00000000; /* 32 bits; cf uint32_t crc32 = 0; */

Podría hacerse, para un uso limitado.


C promueve algunos tipos de forma automática, lo que complica las cosas. Pero para que sea viable, debe tener un par de diferencias adicionales de C tal como existen: en este momento, el estándar aún admite hasta cierto punto los programas K & R C heredados, y eso requiere que los tipos no especificados se manejen de maneras particulares. (Ver, por ejemplo, las reglas para los parámetros de función en ausencia de prototipos. También solía ser posible especificar funciones y variables sin tipo, y se predeterminaban a (int) . (¿Cómo se usan las variables? Clase de almacenamiento solamente static foo; )) Todo este manejo de tipos heredados debería eliminarse antes de que se pueda agregar un nuevo mecanismo de tipos implícitos.


C tiene un conjunto complicado de reglas con respecto a la promoción y conversión de tipos que las personas encuentran confusas, incluso cuando realmente pueden ver los tipos con los que están lidiando. Sospecho que incluso si C tuviera una inferencia de tipo, sería necesario declarar los tipos para evitar errores ridículos cada tercera función.


Es posible hacer alguna inferencia de tipo en C. Eche un vistazo a esta herramienta: http://cuda.dcc.ufmg.br/psyche-c . Puede escribir parte de un programa allí, y reconstruirá las declaraciones de tipos faltantes. Por ejemplo, si lo alimentamos con una variación del programa de Norman:

int length(T p) { if (p == NULL) return 0; else return 1 + length(p->next); }

Entonces psyche-c encuentra estas declaraciones:

#include <stdint.h> #define NULL ((void*)0) typedef int bool; bool false = 0; bool true = 1; typedef struct T {struct T* next;}* T;

Este tipo de reconstrucción de tipo es útil para completar el código, por ejemplo.


GCC 5.1 admite:

  • __auto_type extension, análogo C ++ 11 auto
  • typeof extensión, análoga a C ++ 11 decltype .
  • _Generic clave _Generic C11

Ejemplo:

__auto_type i = 1; assert(_Generic((i), int: 1, default: 0));


Inferir tipos de funciones polimórficas requeriría extensiones dramáticas para el sistema de tipo C. Ejemplo

length(p) { if (p == NULL) return 0; else return 1 + length(p->next); }

Este código tiene que funcionar en cualquier puntero a una estructura (o una unión) con un campo next . Puede ver el polimorfismo de fila, pero al menos, su nuevo sistema de tipo tendrá que ser mucho más expresivo que el sistema de tipo C.

Otro problema apremiante es la operación + sobrecargada. ¿A qué tipo está predeterminado? ¿Desea que esté sobrecargado en cualquier tipo numérico, como Haskell o C ++? Si es así, más extensiones grandes para el sistema de tipo.

La lección más grande es no hacer esto . Los méritos de C (como lenguaje, aparte de las muchas API finas disponibles en C) son

  • Usted tiene control total sobre la representación de sus datos.
  • Cualquier persona que inspeccione el código fuente puede predecir fácilmente los costos de tiempo y espacio.

Esta agenda no es realmente compatible con el polimorfismo, y el polimorfismo es un beneficio principal de la inferencia de tipo. Si la inferencia de tipo es lo que desea, elija uno de los muchos lenguajes finos (F #, Haskell, ML) que lo soportan de forma nativa.