1

I'm writing some python code that calls a C dll via python's ctypes module.

The DLL in question defines some return values as enums in it's header files:

//
// Device status
//
enum {
    FT_OK,
    FT_INVALID_HANDLE,
    FT_DEVICE_NOT_FOUND,
    FT_DEVICE_NOT_OPENED,
    FT_IO_ERROR,
    FT_INSUFFICIENT_RESOURCES,
    FT_INVALID_PARAMETER,
<continued---snip>
};

I'm interfacing this from python, so I don't have native enums. Can I just assume that the contents of the enum start at a value of 0, and increment by 1 for each item? That's easy enough to implement, but it seems like I'd then be relying on implementation details of the compiler.

I've done some digging about the internals of enum variables, but I could not find much about how they work, internally. Only documentation on how to use them in C/C#/whatever.

I know if the enum had constant definitions for the various variables, I could just rely on that, but in this case, I'm interfacing with external code which I don't have access to (just the dll).

Fake Name
  • 5,556
  • 5
  • 44
  • 66
  • The answers below address your question directly. But the weakness in making any assumptions about enum values would be that if the source ever does decide to assign a value to any of those enums, all your hard-coded assumptions would be off. Ideally you'd wrap the enum so that you have some way of actually accessing the values, ensuring that you'll always be doing the comparison you expect. – aruisdante Jul 25 '14 at 01:44
  • @aruisdante - Yeah, that's what bothers me. Realistically, If the enum was restructured, it would break lots of other people's code as well (at least requiring recompilation for anything linking against the DLL), so it's probably safe to assume it won't change. – Fake Name Jul 25 '14 at 01:47
  • Not at all. The whole point of ``enum`` is that as long as you are using the enum, and not relying on the value of the enum, you should always be fine. To *most* user facing code, what the actual value of an enum is should never matter. Anything built by properly treating the enum as a special value, rather than an int, will work. Ergo, the implementer may decide to assign a value so that they could, for instance, get a descriptive error code from the exit value of an application simply by returning the enum. – aruisdante Jul 25 '14 at 01:50
  • For example, if I build an enum to represent indexes into an array of values, I can arbitrarily change the location of the values at those indexes so long as I update the enum, and all of the code built off of that enum will still just work. – aruisdante Jul 25 '14 at 01:52
  • @aruisdante - my point is, if the DLL's enum structure changes, any c-code interfacing with the DLL would have to be recompiled with a header file that reflects the new enum structure. You wouldn't need to change the *user* code, just the header file, but you'd still need to recompile, and old compiled code couldn't link the new dll. – Fake Name Jul 25 '14 at 01:52
  • Ah yes, a recompile is certainly true, but I imagine that would only happen in a new version of the DLL, which would could imply a recompile anyway. But yes, that would be considered an interface change for sure. – aruisdante Jul 25 '14 at 01:53
  • So effectively, restructuring the enum would force a recompilation, whereas if you just update the DLL without changing the API, you can just swap out the dlls without having to change user code (to fix bugs, for example). – Fake Name Jul 25 '14 at 01:54
  • possible duplicate of [Are default enum values in C the same for all compilers?](http://stackoverflow.com/questions/6434105/are-default-enum-values-in-c-the-same-for-all-compilers) – Ciro Santilli OurBigBook.com Jun 18 '15 at 13:01

4 Answers4

4

You're correct.

Unless you specifically assign a value to an enum, it follows these rules:

  • the first one is zero.
  • subsequent ones are one more than the previous one.

For example:

enum {
    ZERO,
    ONE,
    SIX = 6,
    SEVEN,
    TWENTY = 20,
    TWENTYONE
} someNumbers;

works exactly as you would expect, with the enum constants equating to the correct values.

The controlling part of the standard (for C99 anyway) is 6.7.2.2 Enumeration specifiers:

An enumerator with = defines its enumeration constant as the value of the constant expression. If the first enumerator has no =, the value of its enumeration constant is 0.

Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
4

The draft C99 standard in section 6.7.2.2 Enumeration specifiers paragraph 3 says:

If the first enumerator has no =, the value of its enumeration constant is 0. Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant. (The use of enumerators with = may produce enumeration constants with values that duplicate other values in the same enumeration.) The enumerators of an enumeration are also known as its members.

It also provides an example to clarify:

enum hue { chartreuse, burgundy, claret=20, winedark };

and says:

The enumerated values are in the set { 0, 1, 20, 21 }.

It is not clear if you are concerned with the underlying type but paragraph 4 says:

Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined,110) but shall be capable of representing the values of all the members of the enumeration. The enumerated type is incomplete until after the } that terminates the list of enumerator declarations.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
2

The C standard, section 6.7.2.2.1443:

If the first enumerator has no =, the value of its enumeration constant is 0.

and 6.7.2.2.1444:

Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant.

Also, 6.7.2.2.1450 has an example:

EXAMPLE The following fragment:

enum hue { chartreuse, burgundy, claret=20, winedark };

enum hue col, *cp;

col = claret;

cp = & col;

if (*cp != burgundy)

/* ... */

makes hue the tag of an enumeration, and then declares col as an object that has that type and cp as a pointer to an object that has that type. The enumerated values are in the set { 0, 1, 20, 21 }.

Link: The New C Standard: 6.7.2.2

kirbyfan64sos
  • 10,377
  • 6
  • 54
  • 75
0

you can assume that, it is possible for the enum to set a number FT_OK=100, then everything after will increment from there.

Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156