C es un lenguaje de bajo nivel, casi un ensamblador portátil, por lo que sus estructuras de datos y construcciones de lenguaje están cerca del metal (las estructuras de datos no tienen costos ocultos, excepto el relleno, la alineación y las restricciones de tamaño impuestas por el hardware y ABI ). Por lo tanto, C no tiene una escritura dinámica nativa. Pero si lo necesita, podría adoptar una convención de que todos sus valores son agregados comenzando con alguna información de tipo (por ejemplo, algunos enum
...); use union
-s y (para cosas similares a una matriz) miembro de matriz flexible al struct
contener también el tamaño de la matriz.
(cuando programe en C, es su responsabilidad definir, documentar y seguir convenciones útiles, especialmente condiciones previas y posteriores e invariantes; también la asignación dinámica de memoria en C requiere convenciones explícitas sobre quién debería tener free
alguna malloc
zona de memoria activada )
Por lo tanto, para representar los valores que son números enteros en caja, o cadenas, o algún tipo de esquema -como símbolo , o vectores de valores, que va a utilizar conceptualmente una unión etiquetada (implementado como una unión de punteros) -siempre empezando por el tipo de tipo -, p.ej:
enum value_kind_en {V_NONE, V_INT, V_STRING, V_SYMBOL, V_VECTOR};
union value_en { // this union takes a word in memory
const void* vptr; // generic pointer, e.g. to free it
enum value_kind_en* vkind; // the value of *vkind decides which member to use
struct intvalue_st* vint;
struct strvalue_st* vstr;
struct symbvalue_st* vsymb;
struct vectvalue_st* vvect;
};
typedef union value_en value_t;
#define NULL_VALUE ((value_t){NULL})
struct intvalue_st {
enum value_kind_en kind; // always V_INT for intvalue_st
int num;
};
struct strvalue_st {
enum value_kind_en kind; // always V_STRING for strvalue_st
const char*str;
};
struct symbvalue_st {
enum value_kind_en kind; // V_SYMBOL
struct strvalue_st* symbname;
value_t symbvalue;
};
struct vectvalue_st {
enum value_kind_en kind; // V_VECTOR;
unsigned veclength;
value_t veccomp[]; // flexible array of veclength components.
};
Para obtener el tipo dinámico de algún valor
enum value_kind_en value_type(value_t v) {
if (v.vptr != NULL) return *(v.vkind);
else return V_NONE;
}
Aquí hay un "reparto dinámico" de vectores:
struct vectvalue_st* dyncast_vector (value_t v) {
if (value_type(v) == V_VECTOR) return v->vvect;
else return NULL;
}
y un "acceso seguro" dentro de los vectores:
value_t vector_nth(value_t v, unsigned rk) {
struct vectvalue_st* vecp = dyncast_vector(v);
if (vecp && rk < vecp->veclength) return vecp->veccomp[rk];
else return NULL_VALUE;
}
Por lo general, definirá la mayoría de las funciones cortas anteriores como static inline
en algún archivo de encabezado.
Por cierto, si puede usar el recolector de basura de Boehm, puede codificar con bastante facilidad en un estilo de nivel superior (pero inseguro), y varios intérpretes de Scheme se hacen de esa manera. Un constructor de vectores variados podría ser
value_t make_vector(unsigned size, ... /*value_t arguments*/) {
struct vectvalue_st* vec = GC_MALLOC(sizeof(*vec)+size*sizeof(value));
vec->kind = V_VECTOR;
va_args args;
va_start (args, size);
for (unsigned ix=0; ix<size; ix++)
vec->veccomp[ix] = va_arg(args,value_t);
va_end (args);
return (value_t){vec};
}
y si tienes tres variables
value_t v1 = somevalue(), v2 = otherval(), v3 = NULL_VALUE;
podrías construir un vector a partir de ellos usando make_vector(3,v1,v2,v3)
Si no desea utilizar el recolector de basura de Boehm (o diseñar el suyo propio), debe tener mucho cuidado al definir los destructores y documentar quién, cómo y cuándo la memoria debe ser free
-d; Mira este ejemplo. Por lo tanto, puede usar malloc
(pero luego probar contra su falla) en lugar de lo GC_MALLOC
anterior, pero necesita definir cuidadosamente y usar alguna función destructoravoid destroy_value(value_t)
La fortaleza de C es ser lo suficientemente bajo como para hacer posible un código como el anterior y definir sus propias convenciones (en particular para su software).