Home > Software engineering >  Value in a union nested in a struct not updating
Value in a union nested in a struct not updating

Time:10-17

I'm writing a Stack implementation in C that allows for storing any data type. I have this so far:

// stack.h
enum ELEMENT_TYPE {
    ELEMENT_CHAR,
    ELEMENT_INT,
    ELEMENT_DOUBLE,
    ELEMENT_FLOAT
};

typedef struct {
    enum ELEMENT_TYPE type;
    union {
        char val_c;
        int val_i;
        double val_d;
        float val_f;
    };
} Stack_Element;

typedef struct {
    unsigned top;
    unsigned capacity;
    Stack_Element* elements;
} Stack;
Stack* stack_malloc(unsigned capacity) {
    Stack* stack = (Stack*)malloc(sizeof(Stack));
    stack->top = 0;
    stack->capacity = capacity;
    stack->elements = (Stack_Element*)malloc(sizeof(stack->elements) * capacity);
    return stack;
}

void stack_push(Stack* stack, enum ELEMENT_TYPE type, ...) {
    if (isFull(stack)) {
        return;
    }

    va_list ap;
    va_start(ap, type);

    switch(type) {
        case ELEMENT_CHAR:
            printf("Pushing char: %c\n", (char) va_arg(ap, int));
            stack->elements[stack->top].val_c = (char) va_arg(ap, int); // issue
            printf("After pushing: %c\n", stack->elements[stack->top].val_c);
            break;
        case ELEMENT_INT:
            printf("Pushing int: %d\n", va_arg(ap, int));
            stack->elements[stack->top].val_i = va_arg(ap, int); // issue
            printf("After pushing: %d\n", stack->elements[stack->top].val_i);
            break;
        case ELEMENT_DOUBLE:
            printf("Pushing double: %f\n", va_arg(ap, double));
            stack->elements[stack->top].val_d = va_arg(ap, double); // issue
            printf("After pushing: %f\n", stack->elements[stack->top].val_d);
            break;
        case ELEMENT_FLOAT:
            printf("Pushing float: %f\n", (float) va_arg(ap, double));
            stack->elements[stack->top].val_f = (float) va_arg(ap, double); // issue
            printf("After pushing: %f\n", stack->elements[stack->top].val_f);
            break;
    }

    stack->elements[stack->top].type = type;
    stack->top  ;
    va_end(ap);
}

The issue I'm having is in the line stack->elements[stack->top].val_?. In the first printf, where I print Pushing X: %x, the value is correct, so I'll have something like Pushing int: 123.

But then the output for the second printf is After pushing: 291176586, or another garbage value. I'm confused as to why this is happening. Any help is appreciated.

CodePudding user response:

You are using va_arg incorrectly. The man page says:

Each invocation of va_arg() modifies ap so that the values of successive arguments are returned in turn.

but you access it twice. Change your code to:

        char tmp = (char) va_arg(ap, int);  // Save in tmp variable
        printf("Pushing char: %c\n", tmp);
        stack->elements[stack->top].val_c = tmp;
        printf("After pushing: %c\n", stack->elements[stack->top].val_c);
        break;

Besides that your malloc is wrong as it has been pointed out in comments.

stack->elements = (Stack_Element*)malloc(sizeof(stack->elements) * capacity);

shall be

stack->elements = malloc(sizeof(*stack->elements) * capacity);
                                ^
                                notice

That said I prefer the order

stack->elements = malloc(capacity * sizeof *stack->elements);

but it's doing the same.

CodePudding user response:

stack->elements = (Stack_Element*)malloc(sizeof(stack->elements) * capacity);

malloc is wrong, stack->elements is pointer which length is 4. shall be

stack->elements = (Stack_Element*)malloc(sizeof(Stack_Element) * capacity);
  • Related