GCC/Clang-18编译器将类型视为Enum

问题描述 投票:0回答:1
-hello,感谢您的阅读,

我刚刚在我的C程序中遇到了一个错误,尽管我能够找出错误的原因,但我很难合理化编译器的行为,我可以在这里使用一些帮助。我正在努力将一系列值转移到负值,但面临符号转换,导致它导致整数溢出。总而言之,这并不是太令人兴奋了,但这是因为编译器决定应对枚举变量进行未签名,该变量也用于计算中,然后导致该结果的输出也被胁迫到未签名的INT。

最小可再现的代码:

#include <stdio.h> enum UnexpectedlyUnsignedEnum { VALUE1 = 5 }; int main(int argc, char *argv[]) { enum UnexpectedlyUnsignedEnum enum_value = VALUE1; int value1 = (1 - enum_value) / 2; int value2 = (1 - VALUE1) / 2; printf("%i\n", value1); printf("%i\n", value2); }

导致以下输出:

❯ ./example 2147483646 -2 ❯

我可以在某种程度上理解编译器试图“优化” unsigned int的类型,因为它的价值都是积极的(我不确定我同意这是在这里做出的好选择,因为它似乎很可能会引入不必要的错误我可以看到这没有任何好处,何时不需要额外的正整数范围),但是我仍然希望Value1和Value2彼此相等。他们对我而言并不意味着将变量enum_value转换为未签名的值的存储,而Value1仍在签名中。
此外,在使用GCC编译时,我会在启用时会得到符号转换警告,但是尽管有标志并产生与上述相同的输出,但Clang并未提供警告:

GCC

❯ gcc --version gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 ... ❯ gcc -Wconversion -o example example.c example.c: In function ‘main’: example.c:9:18: warning: conversion to ‘int’ from ‘unsigned int’ may change the sign of the result [-Wsign-conversion] 9 | int value1 = (1 - enum_value) / 2; | ❯

clang
❯ clang --version
Ubuntu clang version 18.1.8 (++20240731024944+3b5b5c1ec4a3-1~exp1~20240731145000.144)
...
❯ clang -Wsign-conversion -o example example.c
❯

简而言之,有人可以帮助我理解这里是否破裂了,还是我对这些看起来差异的理解?

Edit:解决问题不是我的问题,它已经解决了。我想理解为什么编译器这样做,因为它对我似乎是违反直觉的。
    

由于您可能还没有使用C 2024,C 2018表示,6.4.4.3 2:

c gcc clang integer-promotion
1个回答
0
投票
标识符被声明为枚举常数具有类型。

再次,在6.7.2.2 3:

枚举列表中的标识符被声明为具有类型
int

的常数

为枚举本身而言,6.7.2.2 4说:

EACH枚举类型应与char,签名的整数类型或未签名的整数类型兼容。类型的选择是实施定义的,但应能够代表枚举所有成员的价值。

the,
int

VALUE1

,而有效地符合C 2018,只要实施已记录了后者。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.