tags:

views:

339

answers:

8

I was doing a code review and I saw assignment of single quoted strings to enum values:

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

While this makes for slightly more readable code (though the enum's meaning should be pretty much in the name of the num), it looks silly to me.

I didn't know you COULD do that and after studying it, I can see that all that happens is the binary value of the "characters" you're using gets thrown into an int.

Does anyone else do this in practice? Or is this a bad practice?

+8  A: 

It is definitely perfectly legal according to ISO C and C++ standards. And it is a fairly reasonable practice if those enum values are serialized to text (e.g. CSV) files as those characters. Otherwise, I don't see much point. I guess it could give some debugging benefits, but all good C/C++ debuggers I know can resolve enum values to corresponding symbols anyway.

Pavel Minaev
or as set as options on a communication protocol or whatever...
kenny
+1 for knowing if it was legal in ISO standards.
Nazadus
+2  A: 

Unless code somewhere expects Option_1 to be 'a', I don't see the benefit.

thedz
+5  A: 

chars are just 1 byte ints, so why not?

CookieOfFortune
+1 As long as it's consistent.
Spencer Ruport
Character literals are bigger than "char"s. This is necessary for getc() to work correctly.
dmckee
That is incorrect, dmckee. According to the standard (2.13.2.1): "An ordinary character literal that contains a single c-char has typechar, with value equal to the numerical value of the encoding of the c-char in the execution character set."
GMan
Er ... ouch.
dmckee
:) In your defense `getc()` *does* return an `int`, so trying to store the result with something like: `char c = getc(...);` is ill-formed.
GMan
This is one of the places where C and C++ differ (or at least C95). In C, a char literal is an int, which is useful in allowing extra values besides characters. In C++, a char literal is a char, which is necessary to allow operator overloading to work.
David Thornley
+2  A: 

Sometimes enums with explicit values are used where the actual value is important. If those values are "ascii value of the letter a" why shouldn't you tell the reader by assigning 'a'?

EricSchaefer
+6  A: 

It looks ok to me, would you rather have:

enum
{
  Option_1 = 97,
  Option_2 = 98
} ;
anon
+1  A: 

You can even assign multibyte "values" that end up being up to 32-bit ints:

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

(With a nod to the dailywtf. :) )

Jim Buck
*running screaming*
EricSchaefer
good lord, does this actually compile? I never knew you could have more than one (non-escape) character in a character literal...
rmeador
also, does endianness come into play here?
rmeador
Yep, it compiles. I came across it myself for the first time pretty recently and couldn't believe it either. I imagine endianness comes into play as much as it would if you were assigning a full 32-bit value to each enum value.
Jim Buck
Bear in mind that "A Multicharacter literal has type int and implementation-defined value" (2.13.2, paragraph 1), so exactly what you get is implementation-defined. I'd expect endianness to matter.
David Thornley
Yes, this is EXACTLY the point of the question. Thing is, it looks silly to me to do what you've listed above. Where on dailywtf did you find this?
bobobobo
The t/f/fnf is from dailywtf, not the 4-byte "character" stuff: http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx . I actually see this being useful if you save these enums to a file so you can inspect the binary file and immediately see the enums. Also, if you inspect memory in a hex dump. (Or if you have a debugger that doesn't show you the enum symbol when looking at the value of a variable whose type is the enum.)
Jim Buck
+8  A: 

That is not a single-quoted string — it's a character literal. Using a character literal in an enum is essentially the same as assigning a char to an int — it's totally legal and can be quite useful in many situations.

Chuck
ty - fixed in question's title
bobobobo
A: 

Hiya, please consider this simple example I've made for you, as you can see it is legal to use enums this way. In my case, I use them as a sort of internal constants for a class. Enjoy.

#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;
}
Maciek
Nice code but it would be more obviously relevant if the example constants were characters. Also, just to be nit-picky, I took a little while longer to understand what you were doing because the way you've laid out your comments for the two enum lines implied (wrongly) to me at least that you were doing one kind of thing with Max_Potatoes and another kind of thing with Max_Tomatoes. In other words the comments initially gave me the impression that Max_Potatoes was an example of something legal and Max_Tomatoes was an example of how class internal enums did something.
Bill Forster
heh, right, should have laid the comments out better
Maciek