my doubt is a general C doubt.. we know if we are using enum the variables which we declare inside automatically increments by one than the previous variable.. but is there any method by which we could make the variables to decrement by one instead of incrementing...
Example
enum my_enum { var1=90, var2,var3 };
for this code var2 and var3 will be 91 & 92 respectively, is there any method (possible) to get them 89 & 88... It was asked in an interview.. any one knows the answer..?
I read your original text as if the 'b' qualifier was required for the C51 architecture, but that the 'd' should be used for all architectures.
My original intention was that the entire comment was applicable to C51, by 'general' I meant that 'd' and a cast to int would work whichever type (char or int) C51 chose to use for the enumeration type.
However, it seems that the standard requires the enumeration constants to be of type int, so this would suggest to me that the enumeration type itself will only hold values representable as type int (although it may be capable of a wider or narrower range), irrespective what actual integer type is chosen for the enumerated type, or rather, what integer type the enumerated type is 'compatible with'. If my interpretation is correct I would therefore suggest that this:
//y is a variable of an enumerated type printf("%d\n",(int)y);
is a general solution outwith C51.
My preference is to avoid enum altogether as it provides a level of abstraction that I don't particularly want.
Indeed, I did qualify my comments as being applicable to C51 though.
I don't think the interpretation need to be generous. The paragraph seems to give a carte blanche. A signed integer type or unsigned integer type means that any integer size is allowed. And they obviously allow either signed or unsigned.
Based on the quotation you provided it seemed to me that the intent was that the implementation should choose an integer type, document it and stick to it. I thought that interpreting it to mean that the implementation could select from the available integer types for every enumerated type created was pushing it a bit - but after a bit of research it seems that is exactly what happens.
I just noted that in the general case, are there any note in the standard that printf() should use %d and not %u? Isn't that one of the non-portable things that people have to be aware of?
No, but C51 uses either signed char or signed int for enumerated types, so %bd or %d would be appropriate, or just %d and cast the enum to int.
Note that this thread doesn't specify any architecture, so I can't assume that we are talking about the C51 compiler.
It is also interesting to note that the enumeration constants have type int, so one might expect that any variable of that type would only need to hold the range of int. I don't know exactly what the outcome of this should be:
enum x{a=MAX_INT, b};
Generally, interview questions aren't about showing what you know, but showing that you can think...
I tend to prefer a combination of both.
By the way, out here in the world wide jungle 'interview question' is a euphemism for 'homework question'.
But one note here about the formatting character for printf() is that the standard says (in 2.7.2.2): "Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined [...]"
In the case of C51 the type can be either char or int depending on the range of values used, so the general solution for printf() would be to cast the parameters to int and use %d.
I think a generous interpretation of the paragraph you quoted would allow this. Maybe.
enum my_enum { var3=88, var2,var1 };
or
enum my_enum { var1=90, var2=89, var3=88 };
Not only off-topic, but also incomplete. No mention of used processor.
Why do you think this is an appropriate question in a thread about the "enum data type"?
Does it have anything whatsoever to do with the preceding discussions?!
and i've got a question about i2c function. 1) is it true that i can set any fixed baud rate (clock) from 0 to 100KHz? 2) if i set the bit I2CFREQ, what value should i put into the register if i'm using crystal 4MHz? 4) if i set the bit I2CFREQ2,SMP=0, is the baud rate fixed to 400KHz or i'm free to set any baud rate from 0 to 400KHZ? what value should i put into I2CADD then using a 20MHZ crystal?
answers are appreciated. Thank you.
I would either go for explicit numbers in the enumerator, or rearrange the symbols to make use of the normal increment.
But on the other hand, I normally don't spend too much time debugging, where I need to look at the raw numbers in the debugger.
If doing embedded, I often try to get a prototype built with extra memory, so I can have a bit of helper info available.
A trick I do use when playing with enumerators is to:
/* operators.h */ T(ADD) T(SUB) T(MUL) T(DIV)
#define T(x) x, enum OP { #include "operators.h" }; #undef T #define T(x) #x, char* op_names[] = { #include "operators.h" }; op = ADD; printf("operator %s\n",op_names[op]);
typedef enum X { base = 90, // 0x5a primus = base - 1, // 0x59 secundus = primus - 1, // 0x58 tertius = tertius - 1 // 0x57 } X;
If you're going to write out the values anyway in the comments, you might as well just assign them directly rather than have to do both that and mess about with the decrementing scheme.
This scheme has the double disadvantage that the comments can get out-of-step with the real values, and you can get the decrementing scheme wrong as well!
typedef enum X { base = 90, primus = 91, secundus = 92, tertius = 93 } X;
makes it really easy to find the value for a symbolic name, or conversely search for the value when you find it in a hex dump.
even easier find in a hex dump
typedef enum X { base = 0x5a, primus = 0x5b, secundus = 0x5c, tertius = 0x5d } X;
now to make it even 'safe' (it is better to confuse the debuuging individual a bit than open the possibility for overlaps)
for debugging (search) purposes I always define constants in hex (or in decimal with a comment of the hex value). Yes, I, once in a blue moon, find things like if (value == symbolic_name) // 0x47 where the value is wrong because of an update, but once you have learned to take such comments with a grain of salt, they are helpful. There is, of course, a 'rule' that when such is found the value in the comment must be corrected in the source.
Erik
I see I neatly demonstrated one reason why you'd use the preprocessor ;)
Where's the edit button?
The preprocessor seems a bit of overkill, unless you expect to change the way the enums hop. Today decrement by one, tomorrow all multiples of 3...
Just decrementing is sufficient.
typedef enum X { base = 90, primus = base - 1, secundus = primus - 1, tertius = tertius - 1 } X;
Any relative scheme is vulnerable to adding and deleting values, as all later values then shift.
It's often handy for later reference and debugging to explicitly assign all the values in a enum, even when they're in incrementing order anyway. This is especially useful for large enums like error codes or some protocol ID numbers. A declaration like
makes it really easy to find the value for a symbolic name, or conversely search for the value when you find it in a hex dump. Any relative method, including the preprocessor, makes this kind of lookup harder. And you don't have to worry about breaking half the values when you add a new one in the middle. It may be worth the tedium simply to list each value.
(And if it's really that huge of an enum, you could always write a little script to generate the C syntax given a list of identifiers.)
View all questions in Keil forum