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};
我正在用 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};