enums and signed/unsigned

Discussion in 'C++' started by Marcel Müller, May 12, 2013.

  1. The following code generates a warning about an singned/unsigned integer
    comparison. I don't understand why.


    typedef enum
    { TATTR_NONE = 0x00U
    , TATTR_SONG = 0x01U
    , TATTR_PLAYLIST = 0x02U
    , TATTR_INVALID = 0x08U
    , TATTR_WRITABLE = 0x10U
    } ATTRIBUTES;

    inline static ATTRIBUTES operator|(ATTRIBUTES l, ATTRIBUTES r) \
    { return (ATTRIBUTES)((unsigned)l|r); } \
    inline static ATTRIBUTES operator&(ATTRIBUTES l, ATTRIBUTES r) \
    { return (ATTRIBUTES)((unsigned)l&r); } \
    inline static ATTRIBUTES& operator|=(ATTRIBUTES& l, ATTRIBUTES r) \
    { return l = (ATTRIBUTES)((unsigned)l|r); } \
    inline static ATTRIBUTES& operator&=(ATTRIBUTES& l, ATTRIBUTES r) \
    { return l = (ATTRIBUTES)((unsigned)l&r); } \
    inline static ATTRIBUTES operator*(bool l, ATTRIBUTES r) \
    { return (ATTRIBUTES)(-l&(unsigned)r); } \
    inline static ATTRIBUTES operator*(ATTRIBUTES l, bool r) \
    { return (ATTRIBUTES)((unsigned)l&-r); } \
    inline static ATTRIBUTES operator~(ATTRIBUTES a) \
    { return (ATTRIBUTES)~(unsigned)a; }

    static unsigned tattr = TATTR_NONE;

    int main()
    { if ( (tattr & (TATTR_PLAYLIST|TATTR_WRITABLE|TATTR_INVALID))
    == (TATTR_PLAYLIST|TATTR_WRITABLE) )
    return 1;
    return 0;
    }


    It seems that the expression
    (unsigned) & (enum type)
    always evalueates to signed int regardless of the definition of the enum
    constants.

    Are enums always signed? And if so, why is

    enum X
    { value = UINT_MAX
    };

    not an error?


    Marcel
     
    Marcel Müller, May 12, 2013
    #1
    1. Advertising

  2. Marcel Müller

    Geoff Guest

    On Sun, 12 May 2013 16:50:47 +0200, Marcel Müller
    <> wrote:

    >Are enums always signed?


    Yes, enums are of type int, not unsigned int.

    >And if so, why is
    >
    >enum X
    >{ value = UINT_MAX
    >};
    >
    >not an error?


    Because UINT_MAX is converted to int and value is evaluated as -1.
     
    Geoff, May 12, 2013
    #2
    1. Advertising

  3. Marcel Müller

    James Kanze Guest

    On Sunday, May 12, 2013 3:50:47 PM UTC+1, Marcel Müller wrote:
    > The following code generates a warning about an signed/unsigned integer
    > comparison. I don't understand why.


    > typedef enum
    > { TATTR_NONE = 0x00U
    > , TATTR_SONG = 0x01U
    > , TATTR_PLAYLIST = 0x02U
    > , TATTR_INVALID = 0x08U
    > , TATTR_WRITABLE = 0x10U
    > } ATTRIBUTES;


    > inline static ATTRIBUTES operator|(ATTRIBUTES l, ATTRIBUTES r) \
    > { return (ATTRIBUTES)((unsigned)l|r); } \
    > inline static ATTRIBUTES operator&(ATTRIBUTES l, ATTRIBUTES r) \
    > { return (ATTRIBUTES)((unsigned)l&r); } \
    > inline static ATTRIBUTES& operator|=(ATTRIBUTES& l, ATTRIBUTES r) \
    > { return l = (ATTRIBUTES)((unsigned)l|r); } \
    > inline static ATTRIBUTES& operator&=(ATTRIBUTES& l, ATTRIBUTES r) \
    > { return l = (ATTRIBUTES)((unsigned)l&r); } \
    > inline static ATTRIBUTES operator*(bool l, ATTRIBUTES r) \
    > { return (ATTRIBUTES)(-l&(unsigned)r); } \
    > inline static ATTRIBUTES operator*(ATTRIBUTES l, bool r) \
    > { return (ATTRIBUTES)((unsigned)l&-r); } \
    > inline static ATTRIBUTES operator~(ATTRIBUTES a) \
    > { return (ATTRIBUTES)~(unsigned)a; }


    > static unsigned tattr = TATTR_NONE;


    > int main()
    > { if ( (tattr & (TATTR_PLAYLIST|TATTR_WRITABLE|TATTR_INVALID))
    > == (TATTR_PLAYLIST|TATTR_WRITABLE) )
    > return 1;
    > return 0;
    > }


    > It seems that the expression
    > (unsigned) & (enum type)
    > always evalueates to signed int regardless of the definition of the enum
    > constants.


    > Are enums always signed?


    An enum defines a new type, which is neither signed nor
    unsigned. When used in an expression, however, in most cases
    (and always when it is an operand to a binary operator, but
    *not* when it is an argument to a function, such as a user
    defined overloaded operator), integral promotion takes place,
    and the enum is converted to the first of int, unsigned, long,
    unsigned long, long long or unsigned long long which can
    represent all of its legal values. In your case, this would be
    an int.

    > And if so, why is


    > enum X
    > { value = UINT_MAX
    > };


    > not an error?


    Because int cannot represent UINT_MAX, so the underlying type
    must be something else. In this case, it must be unsigned int,
    because an implementation isn't allowed to make it a type larger
    than int if either int or unsigned int would work.

    On the other hand, the following

    enum X { a = UINT_MAX, b = -1 };

    must be of a type larger than int, since neither int nor
    unsigned int can represent all of its values; as soon as any
    value is negative, it must be a signed type. Which raises the
    question: what should the type of:

    enum X { a = ULLLONG_MAX, b = -1 };

    be? I would expect it to be a compiler error, but it compiles
    under g++. And g++'s typeinfo stuff is designed to be almost
    totally unusable: typeid(anX | 0).name() returns "n", which of
    course tells me absolutely nothing (but sizeof tells me it has
    16 bytes, which is a good start---except that INT128_MAX
    isn't defined, even when I include <stdint.h>).

    --
    James
     
    James Kanze, May 12, 2013
    #3
  4. Marcel Müller

    James Kanze Guest

    On Sunday, May 12, 2013 7:23:18 PM UTC+1, Geoff wrote:
    > On Sun, 12 May 2013 16:50:47 +0200, Marcel M�ller
    > <> wrote:


    > >Are enums always signed?


    > Yes, enums are of type int, not unsigned int.


    That's completely wrong. Each enum defines a new type. And the
    underlying type can be any promoted integral type, depending on
    the values in the enum.

    > >And if so, why is


    > >enum X
    > >{ value = UINT_MAX
    > >};


    > >not an error?


    > Because UINT_MAX is converted to int and value is evaluated as -1.


    Only if the compiler is completely broken.

    --
    James
     
    James Kanze, May 12, 2013
    #4
  5. Marcel Müller

    Balog Pal Guest

    On 5/12/2013 4:50 PM, Marcel Müller wrote:
    > The following code generates a warning about an singned/unsigned integer
    > comparison. I don't understand why.
    >
    >
    > typedef enum
    > { TATTR_NONE = 0x00U
    > , TATTR_SONG = 0x01U
    > , TATTR_PLAYLIST = 0x02U
    > , TATTR_INVALID = 0x08U
    > , TATTR_WRITABLE = 0x10U
    > } ATTRIBUTES;
    >
    > It seems that the expression
    > (unsigned) & (enum type)
    > always evalueates to signed int regardless of the definition of the enum
    > constants.


    The enumerators do not have 'type' like int or unsigned int, and will
    not reflect the type of "initializers", just the value.

    > Are enums always signed? And if so, why is


    The underlying type is chosen by the compiler to be able to represent
    every value (and all of them or-ed together). for your case it can be
    char, unsigned char, or even a 5-bit thing.

    If you want to force the underlying type, you can do that with C++11
    (and a compiler supporting that feature), look up the changed for enum
    ("enum class" or "strongly typed enum"), those may solve your problem.
     
    Balog Pal, May 12, 2013
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. me2

    hex and unsigned and signed decimal

    me2, Dec 28, 2006, in forum: C Programming
    Replies:
    14
    Views:
    1,687
    Keith Thompson
    Jan 2, 2007
  2. =?utf-8?b?QXNiasO4cm4gU8OmYsO4?=

    Enums without identifier, enums and typedef

    =?utf-8?b?QXNiasO4cm4gU8OmYsO4?=, Jan 19, 2007, in forum: C Programming
    Replies:
    10
    Views:
    1,199
    Keith Thompson
    Jan 20, 2007
  3. kyrpa83
    Replies:
    1
    Views:
    658
    kyrpa83
    Oct 17, 2007
  4. Rob1bureau
    Replies:
    1
    Views:
    843
    joris
    Feb 27, 2010
  5. pozz
    Replies:
    12
    Views:
    796
    Tim Rentsch
    Mar 20, 2011
Loading...

Share This Page