【问题标题】:Value in a union nested in a struct not updating嵌套在结构中的联合中的值未更新
【发布时间】:2021-12-04 03:42:10
【问题描述】:

我正在用 C 语言编写一个 Stack 实现,它允许存储任何数据类型。到目前为止我有这个:

// 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);
}

我遇到的问题在stack->elements[stack->top].val_? 行中。在我打印Pushing X: %x 的第一个printf 中,值是正确的,所以我会有类似Pushing int: 123 的内容。

但是第二个printf 的输出是After pushing: 291176586,或者另一个垃圾值。我很困惑为什么会这样。任何帮助表示赞赏。

【问题讨论】:

  • malloc(sizeof(stack->elements) * capacity) 分配了错误的大小。为避免此类错误,请使用模式p = malloc(sizeof *p * N)
  • 已更改为malloc(sizeof *stack->elements * capacity),但它不起作用。也试过sizeof stack->elements * capacity
  • @Sami 使用stack->elements = malloc( capacity * sizeof *stack->elements);
  • 使用正确的版本,不要“尝试”——C不是试错语言
  • @4386427 有什么区别? sizeof 的优先级高于乘法。

标签: c struct unions


【解决方案1】:

您错误地使用了va_arg。手册页说:

va_arg() 的每次调用都会修改 ap 所以 依次返回连续参数的值。

但您访问它两次。将您的代码更改为:

        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;

除了您的malloc 是错误的,因为它已在 cmets 中指出。

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

应该是

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

也就是说我更喜欢这个顺序

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

但它也在做同样的事情。

【讨论】:

  • 好收获!也许va_fetchva_arg 的更准确的名称。
【解决方案2】:
stack->elements = (Stack_Element*)malloc(sizeof(stack->elements) * capacity);

malloc 错误,stack->elements 是长度为 4 的指针。 应该是

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

【讨论】:

  • 这不会为其他答案添加任何内容。另外:是长度为4的指针。这取决于我的平台(64 位)是 8。
猜你喜欢
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多