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..?
No, there isn't!
"my doubt is a general C doubt"
So you should look for your answer in a general 'C' textbook - or even the 'C' standard itself:
"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"
"...An enumerated type is a user-defined type consisting of a set of named constants called enumerators. By default, the first enumerator has a value of 0, and each successive enumerator is one larger than the value of the previous one, unless you explicitly specify a value for a particular enumerator."
Greetings, Tamir Michael
... enum my_num{var1=90,var2=89,var3=88}; printf("%d,%d,%d",var1,var2,var3); ...
Hello ninja, Did you bother to READ the previous posts? We stated clearly that it is possible if you assign the values yourself! But that was not what the original post asked!
Next step up is to play with the preprocessor.
#include <stdio.h> #define _(x) \ x##tmp1, \ x = base-(x##tmp1-base),\ x##tmp2 = x##tmp1 enum { base = 90, _(alt1), _(alt2), _(alt3) }; int main() { printf("%u %u %u %u\n",base,alt1,alt2,alt3); return 0; }
Impressively horrible. Note that the printf() format specifiers require the 'b' modifier for C51 (and ought to be 'd' rather than 'u').
I'm surprised nobody has suggested:
enum my_enum{var3=88, var2, var1};
or does that not fit with the spirit of the thing?
Well, it doesn't answer the specific question about having the compiler automatically assign decreasing values - although it does achieve the required end of the given example.
If I were the interviewer, I would certainly give credit for that!
Generally, interview questions aren't about showing what you know, but showing that you can think...
Impressively horrible
Yes, something the preprocessor is good at :)
The reason for the %u was that I did test the code with values way above the range of signed integers.
I wanted to compare the two macros:
#define _(x) \ x##tmp1, \ x = 2*base-x##tmp1, \ x##tmp2 = x##tmp1
and
#define _(x) \ x##tmp1, \ x = base-(x##tmp1-base),\ x##tmp2 = x##tmp1
with values large enough that the construct "2*base" would overflow. There should be no difference between the two on a modern processor using two's complement numbers.
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 [...]"
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
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. 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.)
I see I neatly demonstrated one reason why you'd use the preprocessor ;)
Where's the edit button?
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)
typedef enum X { base = 90, // 0x5a primus = base - 1, // 0x59 secundus = primus - 1, // 0x58 tertius = tertius - 1 // 0x57 } X;
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
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!
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]);
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.
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?!