Home > front end >  Can I cast a variable to a type decided during execution in C
Can I cast a variable to a type decided during execution in C

Time:09-09

int* push_back_int(intVector* target, int push)
{
    target->length  ;
    target->val = (int *)realloc(target->val, target->length * sizeof(int));
    target->val[target->length - 1] = push;
    return &target->val[target->length - 1];
}
float* push_back_float(floatVector* target, float push)
{
    target->length  ;
    target->val = (float *)realloc(target->val, target->length * sizeof(float));
    target->val[target->length - 1] = push;
    return &target->val[target->length - 1];
}

Is there any way that I can hold a variable to replace the cast to int* or float* so that i can reuse the same code for multiple variable types using void*

CodePudding user response:

The cast nor the sizeof(type) are not needed: Use target->val = realloc(target->val, target->length * sizeof(target->val)); for both.

Only difference is the function signature.

CodePudding user response:

No. In C the type is only available at compile-time.

You can use void * to pass data back and forth but you need to retain the element size. This approach is referred to as non-type safe (compiler will not catch the wrong "type", say, switching iq and fq below, which will then blow up most impressively at run-time when you get it wrong). Note how calling code handles the cast.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct queue {
    size_t push_length;
    void *val;
    size_t length;
};

void *push_back(struct queue *target, void *push) {
    size_t offset = target->length * target->push_length;
    target->length  ;
    void *tmp = realloc(target->val, target->length * target->push_length);
    if(!tmp) {
       // error handling
       return NULL;
    }
    target->val = tmp;
    return memcpy((char *) target->val   offset, push, target->push_length);
}

int main() {
    struct queue fq = { sizeof(float), NULL, 0 };
    push_back(&fq, &(float) { 2.718 });
    push_back(&fq, &(float) { 3.142 });
    for(unsigned i = 0; i < fq.length; i  ) {
        printf("%u: %f\n", i, ((float *) fq.val)[i]);
    }

    struct queue iq = { sizeof(int), NULL, 0 };
    push_back(&iq, &(int) { 1 });
    push_back(&iq, &(int) { 2 });
    for(unsigned i = 0; i < iq.length; i  ) {
        printf("%u: %d\n", i, ((int *) iq.val)[i]);
    }
}

and the output:

0: 2.718000
1: 3.142000
0: 1
1: 2

Your platform may require specific alignment for each element of val (i.e. for type T push_length = sizeof(T) % alignof(T) ? (sizeof(T) / alignof(T) 1) * alignof(T) : sizeof(T)).

  • Related