• C

enums in C header files

I try to adhere to the following rules with respect to C headers and includes

0) each .h/.c file set is a C "unit"
1) the header file is the "public interface" of the unit
2) it includes prototypes of all functions to be called from outside
3) it does not define any data (e.g. int x;)
3a) this dovetails with the OO principle: for me all data is owned by a unit, no data is shared, if you want to access data in another unit write get/set functions
4) due to (3) a header file can be included more than one time in an application, from any other unit that needs to access it
5) each unit only #includes the other files whose functions it needs to call

This has been a great approach, worked well, minimizes and provides clear indication of the dependencies, kept me out of "include hell", trying to resolve circular dependencies (since it is no problem two units #include-ing each other's headers) or those dumb-seeming long #include lists that big (maybe sloppy?) C applications seem to use.

This has been such a good approach that I wonder if I'm finally doing it as intended, that (1) through (5) is exactly what the C designers had in mind.

But a problem I'm encountering is with enums.  Whereas I can #include a header file with only function declarations multiple times, if it has an enum definition I get a redefinition error.  But I would really like the enum to be part of the public interface; a get_mode function could return a value of one of several mode enumerations, for example.

If I have stumbled upon the "right" way to do this, then is there a way to use enums in the public interface consistent with my rules (1) - (5).

(I know I could use #define "guards" at the beginning and end of the header files to prevent them from being re-included, but I'd prefer not to if I can help it.)

Thanks for any thoughts.
riceman0Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Infinity08Commented:
You can put the typedef for the enum in the header file, and the enum variable definition in the .c file.
/* in the .h : */

typedef enum {
    MET_ONE,
    MET_TWO,
    MET_THREE
} MyEnumType;


/* in the .c : */

MyEnumType instance;

Open in new window

0
Infinity08Commented:
>> (I know I could use #define "guards" at the beginning and end of the header files to prevent them from being re-included, but I'd prefer not to if I can help it.)

You should always add include guards. It's what allows you to correctly include the same header file more than once.
#ifndef MY_HEADER_H
#define MY_HEADER_H

/* contents of the header file */

#endif /* MY_HEADER_H */

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Infinity08Commented:
Note that typedefs can be part of the public interface of a module (and they commonly are). Function declarations, and extern variable declarations are also commonly part of the public interface of a module.

So there's nothing wrong with adding them in the header file (assuming that you want to be able to use them outside of the module) - in fact it's what you'll have to do to write useful code.
0
Choose an Exciting Career in Cybersecurity

Help prevent cyber-threats and provide solutions to safeguard our global digital economy. Earn your MS in Cybersecurity. WGU’s MSCSIA degree program was designed in collaboration with national intelligence organizations and IT industry leaders.

riceman0Author Commented:

Actually I think I was doing the equivalent, right?

enum e_positioner_msg
{
      move_XYstage_move_complete,
      move_Zstage_move_complete,
      move_Zlens_move_complete
};

Neither this nor your typedef syntax allows itself to be redefined (i.e., included from all units that need it) either.

Although I can anticipate your answer: prevent redefinition using include guards.

I thought I had avoided the need for include guards by going to a pure function-based interface (and it felt right).  But if I want to enrich the interface with enums, seems I have to use include guards.

0
Infinity08Commented:
>> Actually I think I was doing the equivalent, right?

That's equivalent (except that a typedef makes it more convenient to use).


>> Although I can anticipate your answer: prevent redefinition using include guards.

Exactly ;)


>> I thought I had avoided the need for include guards

You can declare the same function multiple times within the same compilation unit. The compiler has no problem with that.

However, there is no reason for trying to avoid include guards. It is necessary in many cases, and makes compilation faster in pretty much all cases. Just use them in every header file - no questions asked :)
0
Infinity08Commented:
>> no questions asked :)

Obviously, by that, I didn't mean that you couldn't ask questions ;)
Just that, once you are convinced that include guards are useful, use them in every header file without thinking about it.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.