7

Background

I am trying to assign -1 to an enum variable as shown below:

typedef enum test {
        first,
        second,
}soc_ctr_type_t 

soc_ctr_type_t ctype;

...

switch(type){
   case 1:
       ctype = first;
   break;

   case 2:
      ctype = second;
   break;

   default:
      ctype = -1;
}

If type is the default case, ctype should become -1, but it's not. When I use printf to debug, ctype is 255.

Question

Why does ctype become 255 instead of -1?

Eric Schnipke
  • 482
  • 1
  • 6
  • 22
henry4343
  • 3,871
  • 5
  • 22
  • 30
  • 1
    A few fragments of code usually isn't enough to determine what's going on. That said, the compiler chooses some integer type that accomodates all values of the enumeration. Perhaps it's a good idea to add `typedef enum test { ..., third = -1, } soc_ctr_type_t`, so that the compiler is forced to pick a signed integer type. –  Jun 24 '16 at 10:04
  • If any answer solved your problem, click the big checkbox to accept it as the answer. This will indicate to the community that you found a solution and will give some reputation to you and the answerer. – 2501 Jul 05 '16 at 20:48

2 Answers2

6

Define a enumerator with that value in the enumerator list and the result will be correct:

typedef enum test {
        minus_one = -1 ,
        first,
        second,
} soc_ctr_type_t;

The reason you're seeing 255 is because the compiler chose a narrower unsigned type for this enumerator, because all it can see it first, second, which have the values 0, 1. Thus the type chosen is unsigned char because it can represent those two values.
This type will wrap to 255 from -1.

Enumerators in C aren't a special type, they're represented by an integer type, so you can assign a value to an enumerator that isn't present in the enumerator list.

2501
  • 25,460
  • 4
  • 47
  • 87
  • Does that depend on the compiler ? As for me it is coming as -1. – µtex Jun 24 '16 at 10:32
  • @sas Implementation defined. – 2501 Jun 24 '16 at 10:34
  • 1
    *The reason you're seeing 255 is because the compiler chose a narrower unsigned type for this enumerator,* I'm pretty sure ;-), that the compiler did not chose an unsigned type, but the value is _printed out_ as unsigned type. It is hard to check, what the compiler chosed. (Probably you can check it with the result of a tricky integer promotion. However, there is little reason to decide it.) Chosing an unsigned type would be against the standard: From @sas answer: "can represent all the enumerator values defined" -1 is a enumerator value. You cannot assume that the compiler is broken. – Amin Negm-Awad Jun 24 '16 at 11:33
  • @AminNegm-Awad No, compiler definitely choose unsigned char, otherwise the value wouldn't wrap to 255 even if OP decided to use the specifier u. Unless OP used the specifier hhu, which is an unreasonable assumption. I'm certain OP used d. Choosing an unsigned type in OP's case is conforming. See: 6.7.2.2. p4, the first sentence. – 2501 Jun 24 '16 at 11:36
  • No, because signed `-1` and unsigned `255` has exactly the same bits set (all). The format string tells `printf()` how to interpret this bits even they have a different type. The type is simply irrelevant for `printf()`, it even cannot know it. – Amin Negm-Awad Jun 24 '16 at 11:40
  • Exactly 6.7.2.2 – p4: *but shall be **capable of representing the values of all the members** of the enumeration*. -1 is a member of the enumeration in the Q. Therefore chosing an unsigned type would clearly infringe the standard. – Amin Negm-Awad Jun 24 '16 at 11:43
  • @AminNegm-Awad `because signed -1 and unsigned 255 has exactly the same bits set (all)` You didn't specify the type here, did you mean int and unsigned int. In that case your statement obviously isn't correct. The representation of int with the value -1 is 0xFFFFFFFF and representation of unsigned int with the value 255 is 0x000000FF. Assuming two's complement, and sizeof(int)==4. – 2501 Jun 24 '16 at 11:43
  • `-1 is a member of the enumeration in the Q` No it isn't. Where did you get that idea? The only members are: `first` and `second` which have the values 0 and 1 as I have said in the answer. – 2501 Jun 24 '16 at 11:44
  • Aaaaarg, sorry, thought, that he explicitly added -1. Misread this. – Amin Negm-Awad Jun 24 '16 at 11:44
  • @AminNegm-Awad Ok, great, I would ask you to remove the downvote. – 2501 Jun 24 '16 at 11:48
  • Can I choose enumerator type on compile ? – henry4343 Jun 26 '16 at 03:43
  • 1
    @henry4343 No. If you want values that have greater range than `int` or a specific type, then choose an integer type with desired range and signedness and use `#define` to define constant values that fit into that type. – 2501 Jun 26 '16 at 09:20
2

Just addition to 2501 answered here.

The underlying type of an enumeration is an integral type that can represent all the enumerator values defined in the enumeration. It is implementation-defined which integral type is used as the underlying type for an enumeration except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int.

Another good read Are C++ enums signed or unsigned?

µtex
  • 900
  • 5
  • 12