Duplicate integer values in enum


J

Johannes Bauer

Hi group,

I was just a bit surprised about the behavior of my compiler and traced
a bug down to the fact that enum symbols had duplicate integer values.
Now I'm unsure if that is permissible by the standard (I guess it is,
but it still surprises me). Consider this code:

#include <stdio.h>

enum foo {
MOO,
KOO,
BAR,
ZOO = 0,
};

int main() {
printf("%d\n", MOO);
printf("%d\n", KOO);
printf("%d\n", BAR);
printf("%d\n", ZOO);
return 0;
}

The output of which is on my system using gcc:

0
1
2
0

When I would have thought it'd output:

1
2
3
0

So the reuse of integer values that have explicitly been set by the
programmer is permissible by the C standard?

When I rearrange the values, it works as expected (the compiler only
ever chooses automatic values that are greater than all the previously
parsed values). Is this also guaranteed by the C standard?

Besr regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
Ad

Advertisements

S

Stefan Ram

Johannes Bauer said:
enum foo {
MOO, ....
When I would have thought it'd output:
1

»If the first enumerator has no =, the value of its
enumeration constant is 0.« N1570, 6.7.2.2p3
 
J

James Kuyper

Hi group,

I was just a bit surprised about the behavior of my compiler and traced
a bug down to the fact that enum symbols had duplicate integer values.
Now I'm unsure if that is permissible by the standard (I guess it is,
but it still surprises me). Consider this code:

#include <stdio.h>

enum foo {
MOO,
KOO,
BAR,
ZOO = 0,
};

int main() {
printf("%d\n", MOO);
printf("%d\n", KOO);
printf("%d\n", BAR);
printf("%d\n", ZOO);
return 0;
}

The output of which is on my system using gcc:

0
1
2
0

When I would have thought it'd output:

1
2
3
0

So the reuse of integer values that have explicitly been set by the
programmer is permissible by the C standard?


"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.)" (6.7.2.2p3)
 
J

Johannes Bauer

»If the first enumerator has no =, the value of its
enumeration constant is 0.« N1570, 6.7.2.2p3

....which describes what I'm seeing (and confirms that is indeed by the
standard), but doesn't answer any other of my questions...

Regards,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
J

Johannes Bauer

"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.)" (6.7.2.2p3)

Ah! Interesting. Good to know that it's explicitly permitted to have
duplicate values.

Thanks,
Johannes

--
Zumindest nicht öffentlich!
Ah, der neueste und bis heute genialste Streich unsere großen
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos über Rüdiger Thomas in dsa <[email protected]>
 
B

Barry Schwarz

Hi group,

I was just a bit surprised about the behavior of my compiler and traced
a bug down to the fact that enum symbols had duplicate integer values.
Now I'm unsure if that is permissible by the standard (I guess it is,
but it still surprises me). Consider this code:

#include <stdio.h>

enum foo {
MOO,
KOO,
BAR,
ZOO = 0,
};

int main() {
printf("%d\n", MOO);
printf("%d\n", KOO);
printf("%d\n", BAR);
printf("%d\n", ZOO);
return 0;
}

The output of which is on my system using gcc:

0
1
2
0

When I would have thought it'd output:

1
2
3
0

So the reuse of integer values that have explicitly been set by the
programmer is permissible by the C standard?

The answer to this is yes but it is not part of what you showed. Your
code shows the reuse of an integer value that has been IMPLICITLY set
by the COMPILER.

The situation you describe would occur with

enum foo {
MOO=4,
KOO=3,
BAR,
ZOO = 0,
};

and BAR would have the value 4, the same as MOO
When I rearrange the values, it works as expected (the compiler only
ever chooses automatic values that are greater than all the previously
parsed values). Is this also guaranteed by the C standard?

No! The compiler does not check all previously assigned values. For
an enum constant that is not defined with an explicit value, the
compiler is required to assign a value one greater than the previous
enum constant (or 0 if this is the first enum constant). That is why
BAR is 4 (not 5 as you suppose) in the previous example.
 
Ad

Advertisements

P

Paul N

Hi group,



I was just a bit surprised about the behavior of my compiler and traced

a bug down to the fact that enum symbols had duplicate integer values.

Now I'm unsure if that is permissible by the standard (I guess it is,

but it still surprises me). Consider this code:



#include <stdio.h>



enum foo {

MOO,

KOO,

BAR,

ZOO = 0,

};



int main() {

printf("%d\n", MOO);

printf("%d\n", KOO);

printf("%d\n", BAR);

printf("%d\n", ZOO);

return 0;

}



The output of which is on my system using gcc:



0

1

2

0



When I would have thought it'd output:



1

2

3

0



So the reuse of integer values that have explicitly been set by the

programmer is permissible by the C standard?



When I rearrange the values, it works as expected (the compiler only

ever chooses automatic values that are greater than all the previously

parsed values). Is this also guaranteed by the C standard?

As others have explained, what you're getting is how it is meant to work.

It allows the following:

enum foo {
MOO,
First = MOO,
KOO,
BAR,
ZOO,
Last = ZOO
};

so you can, for example, run through all the possibilities in a loop.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top