Skip to content

Instantly share code, notes, and snippets.

@RaniAgus
Last active June 21, 2023 13:47
Show Gist options
  • Select an option

  • Save RaniAgus/40139d3cdcd7837cb858ad5366dab774 to your computer and use it in GitHub Desktop.

Select an option

Save RaniAgus/40139d3cdcd7837cb858ad5366dab774 to your computer and use it in GitHub Desktop.

Guardar enteros en colecciones

Extraído de: sisoputnfrba/foro#2987 (comment)

Estoy desarrollando el modulo consola. Quiero hacer una "validación" de las instrucciones que están en el pseudocodigo, por ej: si la instrucción existe y si la cantidad de argumentos es correcta.

// ArchivoQueCreaElDiccionarioConTodaLaData.c
void inicializar_diccionario() {
    diccionario_instrucciones = dictionary_create();
    dictionary_put(diccionario_instrucciones, "SET", (void*) 2);
    dictionary_put(diccionario_instrucciones, "MOV_OUT", (void*) 2);
    ...

// ArchivoQueHaceLaValidacion.c
bool esUnaInstruccionValida(Instruccion instruccion) {
    if ( !dictionary_has_key(diccionario_instrucciones,  instruccion.instruccion) ) return false;
    if ( (int) dictionary_get(diccionario_instrucciones, instruccion.instruccion) != string_array_size( instruccion.argumentos )) return false;
    return true;
}

La cuestión es que creo que lo pude implementar bien, osea compila y ejecuta y " todo está bien ", pero me tira el siguiente warning:

warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

La razón del warning es que los nodos (tanto para las listas como para los diccionarios) están pensadas para almacenar un puntero al dato, es decir, un void*, por ejemplo:

typedef enum { MOV_OUT, MOV_IN } t_codigo;

typedef struct {
    t_codigo codigo;
    int parametro1;
    int parametro2;
} t_instruccion;

t_instruccion *instruccion_create(t_codigo codigo, int parametro1, int parametro2) {
    t_instruccion *self = malloc(sizeof(t_instruccion));
    self->codigo = codigo;
    self->parametro1 = parametro1;
    self->parametro2 = parametro2;

    return self;
}

t_list *lista = list_create();
list_add(instruccion_create(MOV_OUT, 120, AX));
list_add(instruccion_create(MOV_IN, BX, 120));

Ahora, si lo que queremos guardar en esa lista o diccionario es solo un número entero, tenemos 2 alternativas:

a) Reservar memoria del tamaño de un int y pasarle el puntero al dato a la lista/diccionario:

int *elemento = malloc(sizeof(int));
*elemento = 42;

t_list *lista = list_create();
list_add(lista, elemento);

int *first = list_get(lista, 0);
printf("el valor guardado es: %d\n", *first);

b) Embeber el int en el nodo (que es lo que estaban intentando hacer), pero para esto no podemos usar int porque la conversión de int a void* no está definida (de ahí el warning). En su lugar, podemos usar su primo hermano intptr_t (que es como "un entero del tamaño de un puntero"), tanto para insertar el valor como para recuperarlo:

t_list *lista = list_create();
list_add(lista, (intptr_t) 42);

intptr_t first = list_get(lista, 0);
printf("el valor guardado es: %d\n", first);

Nota: En el ejemplo los punteros y el intptr_t están midiendo 4 cuadraditos (4 bytes), pero en nuestro caso medirían 8.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment