0

Let's take the following example:

#include <stdio.h>


enum fruit  {APPLE, ORANGE, BANANA};
enum planet {EARTH, MARS, NEPTUNE};


void foo(enum fruit f)
{
    printf("%ld", f);
}


int main()
{
    enum planet p = MARS;

    foo(p); /* compiler doesn't complain */

    return 0;
}

What's the point of enums having names, if that code would compile?
Here is my command line for gcc:

gcc file.c -ansi -Wall -Wextra
Bite Bytes
  • 1,455
  • 8
  • 24
  • Not clear what your problem is. But your code invokes undefined behaviour and any halfway recent compiler/library should warn for a wrong conversion type specifier in `printf`. And why do you return an error from your main? – too honest for this site Sep 07 '17 at 19:30
  • 2
    In C enumerations are basically just symbolic integer constants. However, using the wrong enumeration type is technically undefined behavior. – Some programmer dude Sep 07 '17 at 19:30
  • @Olaf what specifier should I use? (I changed 1 to 0 in the return value of the main function) – Bite Bytes Sep 07 '17 at 19:31
  • @BiteBytes: In case your questions are not some kind of trolling attempt, you are in urgent need of a good C book and learn how to use google or another search provider of your choice. Almost all your question are covered by basic chapters of a textbook. – too honest for this site Sep 07 '17 at 19:36
  • 2
    The reason the compiler does not complain, is not because of the function call, which is correct, but because `long` is the same size as `int` on your system, and an `enum` value has type `int`. If you add a a second parameter, and print both, they will work, even though the behaviour was undefined. But if `long` is larger than `int`, as it may be, you'll possibly get compiler warning, and definite wrong result. – Weather Vane Sep 07 '17 at 19:38
  • @WeatherVane would you please show me how to print an `enum` using `printf`, and what's wrong with the `ld` specifier? – Bite Bytes Sep 07 '17 at 19:39
  • With the `%d` format specifier, as an `enum` value is of type `int`. – Weather Vane Sep 07 '17 at 19:40
  • @WeatherVane: It is completely irrelevant if `long` has the same size as `int`. It has a higher rank, and is a different type. – too honest for this site Sep 07 '17 at 19:40
  • 1
    [Some helpful warnings](https://pastebin.com/maFBuGmy). – WhozCraig Sep 07 '17 at 19:40
  • @WhozCraig but all that the standard says about enum is that is an integral, not an int. – Bite Bytes Sep 07 '17 at 19:41
  • @Olaf I did say it is undefined behaviour, but happened to work if they are the same size. – Weather Vane Sep 07 '17 at 19:41
  • @WeatherVane: I refer to "The reason the compiler does not complain, is not because of the function call, which is correct, but because long is the same size as int on your system" in your comment. The reason it does not complain might be the warning is not enabled. After all there is no requirement for the compiler to emit a dignostic message at all. But tbh, I suspect this is another trolling attempt. – too honest for this site Sep 07 '17 at 19:43
  • @Olaf that is why I wrote "you'll **possibly** get compiler warning" – Weather Vane Sep 07 '17 at 19:44
  • @Olaf are there any more options I can use besides `-Wall -Wextra` with gcc? – Bite Bytes Sep 07 '17 at 19:45

2 Answers2

5

AFAIK, in C99, the "tag" (what you call the name, e.g. fruit) of enum is optional.

So

enum { BLACK, RED, GREEN, BLUE, YELLOW, WHITE };

is acceptable (and quite useful)

and you can even give values integral constants

enum { RFCHTTP =2068, RFCSMTP= 821 };

which is a more modern way than

#define RFCHTTP 2068
#define RFCSMTP 821

(in particular, such enum values are known to the debugger, when you compile with debug info)

But in C enum are mostly integral values. Things are different in C++.

Regarding using %ld format control conversion for printf with an enum argument it is probably some undefined behavior (so you should be scared). Probably gcc -Wall -Wextra might warn you.

BTW, GCC has many options. Read its chapter on Invoking GCC.

I recommend (in 2017) coding for C99 or C11, not old 1989 ANSI C.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Thank's for you answer, first I'm compiling with the option `-ansi`, which restrict my code to C89 (see the tag). Second I have this question: "why should I use `%d` specifer to print an `enum`"? cause `%d` is used to print integers, and enums are of integral types and not necessarily integers, wouldn't be more appropriate to use the `%ld`? – Bite Bytes Sep 07 '17 at 19:52
  • I believe that using a 1989 standard in 2017 is unreasonable for a language with both 1999 and 2011 standards (and both being better than the ANSI one) – Basile Starynkevitch Sep 07 '17 at 19:53
  • I'm not using it, I'm just trying to learn as possible as I could about it, before I move on, because it doesn't make sense to praise K&R book everywhere then tell people stay away from that version of C – Bite Bytes Sep 07 '17 at 19:57
  • And please, if you could, I'm still waiting for an answer to the question about the specifier. – Bite Bytes Sep 07 '17 at 19:58
3

Even if your code will compile, the following will not

enum fruit *f = 0;
enum planet *p = f;

since enum fruit and enum planet are two different unrelated types.

What you observe in your code sample is a mere implicit conversion between two enum types in value context. In exactly the same way you can implicitly convert a double value to int type. Yet, I hope, you will not use that to conclude that there's no reason to distinguish between double and int.

Your question would be more justified if you asked "Why do we have implicit conversions between unrelated enum types?" As for enum types having distinctive names... there are perfectly good reasons for that.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765