C 中匿名联合赋值的警告

Warning for anonymous union assignment in C

我正在用 C 构建一个堆栈的小型演示。由于 C 没有例外,我正在尝试结果模式(类似于 Swift 5 中的 Result<>)来处理创建、推送和弹出时出错。

我创建了一个包含错误枚举的头文件:

typedef enum {
  no_error,
  illegal_stack_capacity,
  out_of_memory,
  stack_element_too_large,
  stack_full,
  stack_empty
} stack_error;

堆栈本身的结构(为了具体起见,我使用了一堆字符串,因为此时我只是在试验:

typedef struct {
    char** data;     // array of strings, capacity set on create()
    int capacity;    // have to store this separately!
    int top;         // index of next slot to fill, also the size
} stack;

现在为了捕获错误,我想我会构建一个包含错误部分和成功部分的小结构。在我进行试验时,我试图让错误部分执行双重任务,既作为可区分的联合标记,又能捕获错误。这可能是一个 hack,但它导致了(我认为可能是)一个有趣的问题。

typedef struct {
    stack_error error;
    union {
        stack* stack;    // because create() returns a stack
        char* value;     // because pop() returns a string
    };
} result;

供参考(抱歉造成混乱),我有这些功能:

result create(int capacity);
int size(const stack* s);
bool is_empty(const stack* s);
bool is_full(const stack* s);
stack_error push(stack* s, char* item);
result pop(stack* s);
void destroy(stack** s);

现在的问题是,每次我构建一个 result 对象时,C 编译器 似乎总是假定我的 result 的匿名联合组件结构应该是 stack*。当我写的时候,在我的 create 函数中

return (result){no_error, s};

编译器没有问题,但是当我在我的 pop 函数中写这个时:

return (result){no_error, popped_value};

编译器给我一个警告:

boundedstack.c:57:31: warning: incompatible pointer types initializing
  'stack *' with an expression of type 'char *'
  [-Wincompatible-pointer-types]
return (result){no_error, popped_value};
                          ^~~~~~~~~~~~

我知道我可以通过 (1) 使联合不是匿名的或 (2) 为 stack_result(对于创建)和 string_result(对于弹出)创建单独的类型来解决这个问题,也许我 应该 这样做,但我对这个警告很感兴趣,想知道是否有任何 C 语言专家知道该语言中是否有任何内容指示了这种警告,或者警告是否只是编译器实现者决定说“嘿,好吧,我只是假设联合的正确类型是我看到的第一个”。代码工作得很好,但在我看来 编译器本可以做得更好。或者它可以吗? 编译器可以做得更好吗?或者在编译器中进行检查会不会太昂贵?

(我真的不想禁止警告,因为那是不好的做法。我尝试匿名联合是不是错了?)

解决该错误的一种方法是使用指定的初始化:

return (result){.error=no_error, .value=popped_value};