C/C++ Are Enums and Unions Useful in Real Life Programming?

  • Thread starter Thread starter yungman
  • Start date Start date
  • Tags Tags
    C++
AI Thread Summary
Enums and unions are valuable in real-life programming, particularly in C and C++, where unions allow for different views of the same data and are essential for memory-efficient data structures. While enums provide a way to define a set of named integral constants, they should not be treated as interchangeable with integers, as this can lead to logical errors in code. Modern C++ recommends using type-safe alternatives like std::variant for unions and enum class for enumerations to enhance type safety and clarity. The discussion emphasizes the importance of understanding these concepts fully rather than dismissing them based on assumptions. Overall, both enums and unions serve critical roles in efficient and effective programming practices.
yungman
Messages
5,741
Reaction score
294
I have a quick question. The last 15 pages of chapter 11 is on Unions and Enumerators. Are they useful in real life programming? I can see some usefulness of Enumerators with well defined limited set of elements. The only reason for Union is to save a little memory.

But what do I know.
 
Technology news on Phys.org
yungman said:
The only reason for Union is to save a little memory.

Not necessarily so. A C union has historically been used to express both one-of-many types and as a mechanism to reinterpret bit-patterns where, for instance, you set a double value and then read out the bytes for that or visa versa. You can think of the last use as a kind of use as a data structure that includes a number of user defined casts that "follows" the data type instead of having to be applied at every point where the data is used in the code.

Note that for expressing one-of-many types in modern C++ it is recommended to use a type-safe variant instead, like for instance std::variant. These are very useful for expressing a one-of-many value types in a fairly flexible way, as opposed to having to code a fully defined "union" value class yourself or fall back using references.
 
yungman said:
The only reason for Union is to save a little memory.

It is not a good idea to not read the chapters explaining a topic, guess at the content, and decide you don't need to know it based on that guess.

Unions exist to give you two views of the same data. For example, if I were writing some sort of communications protocol, I might want to view the same data as a stream of bytes or as the floating point numbers (for example) carried in these bytes.

While they do save a tiny bit of memory, that's not why we use them.
 
  • Like
Likes phinds and berkeman
Vanadium 50 said:
Unions exist to give you two views of the same data. For example, if I were writing some sort of communications protocol, I might want to view the same data as a stream of bytes or as the floating point numbers (for example) carried in these bytes.

While they do save a tiny bit of memory, that's not why we use them.
Agreed. We use them in our C code for many of the structures that represent the various options for packet address format (unicast, multicast, MAC ID addressing, etc.) and protocol data unit formatting.
 
  • Like
Likes Vanadium 50
You don't use unions often, but when you need them, you really need them.
 
  • Like
Likes phinds and jedishrfu
One thing to be aware is that C/C++ besides being an effective applications programming language, is also an effective systems level language where it's important to access any kind of data in any kind of way. Usually this is where unions come into play.

Here are some examples:
- convert big-endian format to little endian format
- extract or set some bits or bytes in a register
- bit packed data in messages...
- binary messages with a type specifier (ie type field specifies which part of the union is to be used)

More arcane examples here:

https://stackoverflow.com/questions/252552/why-do-we-need-c-unions
 
ha ha, it's easier to just do it than to think more whether it's necessary or not. I just went through Union and Anonymous Union, piece of cake. Only difference is using the if() statement to decide which one to use. Or using switch for more than two cases. All just to make sure one at a time and don't cross erase things.

Enumerated looks to be very simple too. I think I am going to finish chapter 11 in a day or so. This complete the regular first semester course of C++ class. Anything more is bonus. I am going to study chapter 12, 13 and 14. Maybe chapter 15 on Inheritance, Polymorphism and Virtual Functions.
 
yungman said:
What can I do to make it to display Mon, Tue, Wed etc.?

In C and C++ an enumeration (and enumeration class) type is at runtime treated as an integral type and never as a string, so in principle you have to map to and from strings (the value names) yourself [1].

Some frameworks and libraries may provide support or wrappers for providing this conversion more or less automatic. For instance, the Qt framework has an extensive meta data system (including conversion to and from strings) which also include support for enumerations [2].

[1] https://stackoverflow.com/questions/207976/how-to-easily-map-c-enums-to-strings
[2] https://doc.qt.io/qt-5/qobject.html#Q_ENUM
 
  • Like
Likes yungman
Filip Larsen said:
In C and C++ an enumeration (and enumeration class) type is at runtime treated as an integral type and never as a string, so in principle you have to map to and from strings (the value names) yourself [1].

Some frameworks and libraries may provide support or wrappers for providing this conversion more or less automatic. For instance, the Qt framework has an extensive meta data system (including conversion to and from strings) which also include support for enumerations [2].

[1] https://stackoverflow.com/questions/207976/how-to-easily-map-c-enums-to-strings
[2] https://doc.qt.io/qt-5/qobject.html#Q_ENUM
Thanks, I look them up, it's beyond my knowledge at this point. It's easy enough to just use switch case to do it.
 
  • #10
yungman said:
It's easy enough to just use switch case to do it.

<sigh>

That's not what enums are for.

You ask a lot of questions. A LOT of questions. Really, really a LOT of questions. And yet, your reply to people who try and help is often "I don't need to learn that", or "I am not going to do that" or "that's not the order I want to follow" or "I know better than you because I've been doing this before you whippersnappers were born" or...or...or...

If you want help, you might think about being a little less difficult to help.

On the point in question, you should think of enums as their own type, and not count on the fact that under the hood these are integers. Yes, "red" might be internally expressed as 1 and "blue" as 2, but "red plus green" makes no sense, and if you want it to be 3, you should not be using enums.
 
  • #11
Vanadium 50 said:
<sigh>

That's not what enums are for.

You ask a lot of questions. A LOT of questions. Really, really a LOT of questions. And yet, your reply to people who try and help is often "I don't need to learn that", or "I am not going to do that" or "that's not the order I want to follow" or "I know better than you because I've been doing this before you whippersnappers were born" or...or...or...

If you want help, you might think about being a little less difficult to help.

On the point in question, you should think of enums as their own type, and not count on the fact that under the hood these are integers. Yes, "red" might be internally expressed as 1 and "blue" as 2, but "red plus green" makes no sense, and if you want it to be 3, you should not be using enums.
I was hoping to have a simple way like static_caste<>() to convert from number to enumerator. But when I read it, it's a lot more involve that make switch case not bad at all. That's why I decided to just use switch case. I know it's not enums is for, the book just settle with displaying 0, 1, 2..etc. I just want to see there's any easy way than switch case to switch to Mon, Tue. Apparently not.
 
  • #12
yungman said:
I was hoping to have a simple way like static_caste<>() to convert from number to enumerator.

I assume you mean cast and not caste.

If you are trying to convert between an enum and its underlying implementation (presumably int) you are doing something wrong. The whole point of enum is to hide the underlying implementation.
 
  • #13
yungman said:
I was hoping to have a simple way
It's pretty simple.
C++:
#include <iostream>
#include <string>
using std::string;
using std::cout;

enum Days
{
    Sun = 0,
    Mon,
    Tue,
    Wed,
    Thu,
    Fri,
    Sat
};

int main()
{
    string DaysOfWeek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
    for (int day = Sun; day <= Sat; day++)
        cout << DaysOfWeek[day] << "\n";    
}
The code iterates through the enumeration, and converts each enum value to its corresponding string representation.
 
  • #14
You don't need to set Sun = 0. The compiler will do it for you.

C++'s handling of enums is quite poor. It will treat as valid Mon+Tue, and return Wed. It will also treat as valid Fri+Sat, and return 11. That is very likely not what you want.

Pascal does it better. Ada better still. (And when was the last time you heard something good about Ada?)
 
Last edited:
  • #15
Vanadium 50 said:
You don't need to set Sun = 0. The compiler will do it for you.
I thought of that as I was writing the code; i.e., that by default an enum starts off at zero. In any case, conversion is pretty straightforward.
 
  • #16
Mark44 said:
by default an enum starts off at zero
A compiler may make that decision, but the definition of enum says nothing about "default" mapping between elements defined by enum and integers. I am especially wary about assuming that any element has the value 0.

Anecdote: In the late 1980s I was tasked with finding faults in a large, modular C program that was destined to run from EPROM (Erasable Programmable Read Only Memory). It usually ran well until something unusual happened an then it crashed spectacularly. I insisted on getting a debug emulator, connected it and defined the memory areas (ROM - RAM - I/O). The debug emulator gave me the option on "break on write to ROM", which I thought was a sensible option and turned it on. Started the emulator - and it went into a break immediately.

It turned out that some optimist assumed that a returned pointer always pointed to something meaningful - but the standard rule in C is that any function returning a pointer has the option of returning a null pointer to indicate an error. And a null pointer (referencing the address 00) also pointed to the start of the ROM. Getting people to check the returned value before using it took half a year - there was always one more unchecked null pointer. And when somebody called out "Now it works!", it turned out that they had disabled the "break on write to ROM" option.
 
  • #18
Yes, C++11's enum class recognizes the shortcomings of C++'s enums.

Let me also repeat my earlier comment: The reason you use an enum is to hide the underlying representation. If you want to look at the underlying representation, you're doing something wrong!
 
Last edited:
  • Like
Likes pbuk
  • #19
And let me echo that...
Vanadium 50 said:
The reason you use an enum is to hide the underlying representation. If you want to look at the underlying representation, you're doing something wrong!
 
Back
Top