I would like to create an enumerated list of negative values for error handling so <0 is an error and >=0 is valid for some function:
int f() {
if (someerror())
return ERR_TYPE_2;
else
return 0;
}
main() {
if (f() < 0) blow_up();
else profit();
}
I know that enumerations in C (enum) count up from 0 by default, and I could assign them like so:
enum {
ERR_TYPE_1 = -1,
ERR_TYPE_2 = -2,
ERR_TYPE_3 = -3
}
or I get arbitrary negative enums "automatically" by starting at an arbitrary negative value for which the enum will never reach:
enum {
ERR_TYPE_1 = -100,
ERR_TYPE_2 // -99
ERR_TYPE_3 // -98 ...
}
Question: Is there a way to tell enum to start at -1 and count negative instead of using the methods above?
Update for commenters:
I have no objection to hard-coded error values, in fact that's what I usually do (either as a define or an enum).
This question is really about whether C officially supports negative enums in some unknown-to-me syntactic sugar that wasn't forthcoming after some search-fu.
I would advise against automatic numbering of error codes. It creates an awful user experience for the programmer calling your function, who gets an error -67 and has to go count entries in your header file's error listing (skipping commented lines, naturally). Much nicer if the error codes have explicit values. Autonumbering also makes it too easy to change numbering of existing error codes, making it impossible to compare logs from different versions of your software.
But if you insist, keep reading:
You can do this using the "X-MACROS" pattern. The general concept is that they define the list a single time, but generate multiple source code snippets from that list, with the transformation from list to source code changing.
myenum.enm
ENM_X(ERR_NOTFOUND)
ENM_X(ERR_TOOHARD)
ENM_X(ERR_STACKOVERFLOW)
enum myenum_helper
{
skipzero,
#define ENM_X(ID) enumreversinghelper_##ID,
#include "myenum.enm"
#undef ENM_X
};
enum myenum
{
#define ENM_X(ID) ID = -enumreversinghelper_##ID,
#include "myenum.enm"
#undef ENM_X
};
You can do it without #include by relying on the delayed expansion of macros inside macro bodies, but that requires a preprocessor guru to understand and maintain. This version is pretty straightforward. As a bonus, you can now #include the same file in an strerror()-like function that automates mapping numeric codes to names.
On the other hand, if you're willing to delve into the intricacies of the preprocessor macro semantics, you could hide the complicated parts and make usage much nicer:
#include "reversed_enum.h"
REVERSED_ENUM(myenum, ERR_NOTFOUND, ERR_TOOHARD, ERR_STACKOVERFLOW)
What you want is not possible. Enum identifiers without an explicit value assigned are required to have the value of 1 more that the prior identifier, or 0 for the first one.
This is spelled out in section 6.7.2.2p3 of the C standard regarding Enumeration Specifiers:
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.
While it's possible that a compiler may support a different ordering as an extension, I'm not aware of any that support such a feature.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With