Saturday, March 10, 2012

Bug: C enum variables stored as unsigned ints

I read in K&R that enum values are basically int constants (like #defines in that way), and so enum variables are equivalent to ints. However, in C (not C++ though), you may assign any int value to an enum variable--even if that int value is not one of the listed values in the enum definition. You can do this without even raising a compiler warning.

In a program I was working on, I took advantage of that. I had an enum of values 0 through 7:

  enum direction { N, NE, E, SE, S, SW, W, NW};

In a particular function, I was scanning a map for a target in different directions and decided to return -1 if there was nothing interesting found in any direction. However, this led to strange bug.

The following program shows this bug clearly:

#include <stdio.h>

enum nums {zero, one, two, three};

int main(void) {  
  //using an enum as normal
  enum nums myNum = zero;
  printf("zero == %d\n", myNum);
  //assigning int value to an emum
  myNum = -1;
  printf("-1 == %d\n", myNum);
  if (myNum >= 0) {
    printf("%d >= 0\n", myNum);
  }else {
    printf("%d < 0\n", myNum); 

This program prints:

 zero == 0
 -1 == -1
 -1 >= 0

I'm using GCC, and the manual itself says: "By default, these values are of type signed int" and "Although such variables are considered to be of an enumeration type, you can assign them any value that you could assign to an int variable".

However, further research shows that gcc will store an enum variable as an unsigned int if you have no negative values in your defined enum. For example, if I add neg = -1 as an extra value to my enum nums above, the output of the program changes to what I expect: -1 < 0.

Apparently the section of the C99 standard (draft version) clarifies that this is allowed--that the particular int format used is implementation-dependent. An official version of the C90 standard is not freely available for comparison. -std=c90 doesn't change gcc's behavior on this issue.


  1. That is weird. I didn't know enums existed in C. Did Julia talk about it? I've been watching her lectures every now and then but haven't caught up with her most recent ones yet. (Tell her I said, "Hi.")

    Assigning values to enums sounds like something C would let you do: C lets you do anything, for the most part. I think I'll stick to Java for the foreseeable future.

    1. No, I learned about them from K&R. :) Julia's been using a lot of structs though.

    2. I love K&R. Are you making your students read the entire book? I should have. Maybe next time. ;)

  2. P.S. Out of curiosity, are all of the lectures for ICS 212 all online this semester?

    1. Yes. Student opinion is mixed on whether this is good thing or not. Some like it and some don't.

    2. Personally, I don't really like it as students don't get a chance to interact with the professor unless she shows up at the labs. I think because the lectures and labs are late at night, she opted to go online. That's my guess.