将int x = 'abc'赋值给x?

3

我正在进行代码审查,看到将单引号字符串分配给枚举值:

enum
{
  Option_1 = 'a',
  Option_2 = 'b'
} ;

虽然这使得代码稍微更易读(尽管枚举的含义应该在名称中明确),但我觉得这看起来很傻。

我不知道你能否这样做,在研究后,我可以看出您使用的“字符”的二进制值只是被抛入int中。

其他人是否会实践这样做?还是这是一种不好的做法?


2
顺便提一下:您的主题行(“分配int x ='a'”)表明枚举和int是相同的。虽然相似,但它们是不同的,不应该互换使用。 - abelenky
2
另外,如果要挑剔一点的话,在这里并没有进行任何赋值操作。 - anon
好的,枚举中的个别元素是int类型的,对吗? - GManNickG
1
@GMan:请参见https://dev59.com/OHNA5IYBdhLWcg3wBpBm,“C++枚举的基础类型是什么”。 - maxwellb
啊,我现在明白了。标准上说的是“未指定的整数”。 - GManNickG
显示剩余3条评论
8个回答

9

根据ISO C和C++标准,这绝对是完全合法的。如果这些枚举值被序列化为文本(例如CSV)文件中的字符,则这是一种相当合理的做法。否则,我认为没有太多意义。我猜它可能会带来一些调试的好处,但我知道所有好的C/C++调试器都可以将枚举值解析为相应的符号。


8

这不是一个单引号字符串,而是一个字符字面量。在枚举中使用字符字面量实质上与将 char 赋值给 int 相同,完全合法,并且在许多情况下非常有用。


标题已修正。 - bobobobo

6
我认为这看起来没问题,你更倾向于什么样的呢:
enum
{
  Option_1 = 97,
  Option_2 = 98
} ;

5

字符仅是1字节的整数,为什么不呢?


字符字面量比“char”更大。这对于getc()正常工作是必要的。 - dmckee --- ex-moderator kitten
这是不正确的,dmckee。根据标准(2.13.2.1):“包含单个c-char的普通字符字面值具有char类型,其值等于执行字符集中c-char的编码的数值。” - GManNickG
在您的防守中,getc()确实返回一个int,因此尝试使用类似于 char c = getc(...); 的东西来存储结果是不合适的。 - GManNickG
这是 C 和 C++(或至少 C95)的一个不同之处。在 C 中,char 文字常量是 int 类型,这对于允许除字符外的额外值非常有用。而在 C++ 中,char 文字常量是 char 类型,这是为了使操作符重载能够正常工作必需的。 - David Thornley

2
除非代码中某处期望 Option_1 为 'a',否则我看不出有什么好处。

2
有时候,当枚举值的实际值很重要时,会使用具有显式值的枚举。如果这些值是“字母a的ascii值”,为什么不通过赋值'a'来告诉读者呢?

1

你甚至可以分配多字节的“值”,这些值最终可以达到32位整数:

enum t_f_fnf
{
    true = 'true',
    false = 'fals',
    file_not_found = 'fnf!'
};

(向dailywtf致敬。 :))

天啊,这真的能编译吗?我从不知道字符字面量中可以有一个以上(非转义)字符... - rmeador
还有,这里是否涉及字节序问题? - rmeador
是的,它可以编译。我最近第一次遇到它自己,也不敢相信。我想如果你将一个完整的32位值分配给每个枚举值,那么字节顺序也会起作用。 - Jim Buck
2
请注意,“多字符字面值的类型为int,其实现定义的值”(2.13.2,第1段),因此您得到的内容是实现定义的。我希望端序很重要。 - David Thornley
是的,这正是问题的关键。问题在于,你列出的方法对我来说看起来很傻。你在dailywtf上找到了这个吗? - bobobobo
t/f/fnf来自dailywtf,而不是4字节的“字符”东西:http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx。如果您将这些枚举保存到文件中,以便您可以检查二进制文件并立即看到枚举,则我认为这实际上很有用。此外,如果您在十六进制转储中检查内存(或者如果您有一个调试器,在查看类型为枚举的变量值时不会显示枚举符号),也可以使用它。 - Jim Buck

-1

嗨,考虑一下我为您制作的这个简单示例, 正如您所看到的,使用枚举是合法的。在我的情况下,我将它们用作类的内部常量。享受吧。

#include <iostream>

using namespace std;

class VegetableBasket
{
    enum { Max_Potatoes = 2 };  // This is a legal usage...
    enum { Max_Tomatoes = 3 };  // In here the enums serve as class's internal constants
    public :
        // Constructors
        VegetableBasket() : tomatoes(0), potatoes(0) {}
        VegetableBasket(int t, int p) : tomatoes(t), potatoes(p) 
        { 
            if(tomatoes > Max_Tomatoes) 
                tomatoes = Max_Tomatoes;
            if(potatoes > Max_Potatoes)
                potatoes = Max_Potatoes;
        }
        // Accessors
        int getMaxPotatoes() const { return Max_Potatoes; }
        int getMaxTomatoes() const { return Max_Tomatoes; }
        int getPotatoes() const { return potatoes; }
        int getTomatoes() const { return tomatoes; }
    private :
        int tomatoes;
        int potatoes;
};


void main()
{
    VegetableBasket basket1(1, 1);
    VegetableBasket basket2(5, 6);

    cout << "The basket holds : " << basket1.getMaxPotatoes() 
         << " max potatoes, and " << basket1.getMaxTomatoes()
         << " max tomatoes" << endl;

    cout << "Basket 1 holds : " << basket1.getPotatoes()
         << " potatoes and "    << basket1.getTomatoes()
         << " tomatoes" << endl;

    cout << "Basket 2 holds : " << basket2.getPotatoes()
         << " potatoes and "    << basket2.getTomatoes()
         << " tomatoes" << endl;
}

不错的代码,但如果示例常量是字符,它将更明显相关。另外,只是挑剔一下,我花了更长的时间来理解你在做什么,因为你为两个枚举行布置注释的方式让我(错误地)认为你正在使用Max_Potatoes做一种事情,而使用Max_Tomatoes做另一种事情。换句话说,注释最初给我留下的印象是Max_Potatoes是某种合法事物的示例,而Max_Tomatoes是类内枚举如何执行某些操作的示例。 - Bill Forster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接