C++ packing a typedef enum
Asked Answered
M

7

5
typedef enum BeNeLux
{
   BELGIUM,
   NETHERLANDS,
   LUXEMBURG
} _ASSOCIATIONS_ BeNeLux;

When I try to compile this with C++ Compiler, I am getting errors, but it seems to work fine with a C compiler. So here's the question. Is it possible to pack an enum in C++, or can someone see why I would get the error?

The error is:

"semicolon missing after declaration of BeNeLux".

I know, after checking and rechecking, that there definitely is a semicolon there, and in any places required in the rest of the code.

Addendum:

_PACKAGE_ was just an example. I am renaming it.

_ASSOCIATIONS_ is not a type of BeNeLux:

#define _ASSOCIATIONS_ __attribute__((packed))

The code is iffed, but only to make sure it is GNU C/C++.

#if defined (__GNUC__) 
#define _ASSOCIATIONS_ __attribute__((packed))
#else
#define _ASSOCIATIONS_

Would this cause problems? I thought (GNUC) worked for both C and C++

Addendum 2:

I even tried

#ifdef __cplusplus
extern "C" {
#endif

    typedef enum BeNeLux
    {
       BELGIUM,
       NETHERLANDS,
       LUXEMBURG
    } _ASSOCIATIONS_ BeNeLux;

#ifdef __cplusplus
}
#endif

No joy. Anyone?

Note: -fshort-enums is not a possibility; looking for a programmatic solution.

Meadows answered 7/5, 2010 at 21:14 Comment(8)
This is a nonstandard feature. What C compiler are you using?Derinna
Using gcc 3.3.5 or lower (have to use this older version)Meadows
What do you mean by packing an enum? Making the underlying type as small as possible?Winniewinnifred
Both _PACK_ and _PACKAGE_ are illegal as user-defined macro names. Names beginning with underscore(s) are basically reserved for compiler's internal identifiers and standard library implementations. (The rules are more complicated, but just don't use leading underscores.)Octennial
@UncleBens: Leading underscores is not a problem here, since I can compile fine with a C compiler. @David: Yes. This is for embedded programmingMeadows
@Sagar: "can compile" does not mean legal. What UncleBens said is correct. But that's besides the point.Upbow
@Evan: I realise that, but like I said...that is not the issue.Meadows
While it would be good to have the answer here on SO too, doesn't it make sense to ask this on a GCC mailing list?Northampton
U
4

UPDATE:

For C++11 and later, you can specify the underlying type of enums. For example:

enum BeNeLux : uint8_t {
   BELGIUM,
   NETHERLANDS,
   LUXEMBURG
};

But this only applies if the code will be C++ only. If the code needs to be compatible with both C and C++, I believe my original answer still applies.


I don't think that there is something that does exactly what you want here. I assume you are trying to create a type that is the smallest type for the enum's range.

If you need this type of control, I would recommend something like this:

typedef unsigned char BeNeLux;
static const BeNeLux BELGIUM = 0;
static const BeNeLux NETHERLANDS = 1;
static const BeNeLux LUXEMBURG = 2;

not quite as pretty and possibly a little less type safe. But has the effect that you want. sizeof(BeNeLux) == 1 and you have a named constant for all values in the range. A good compiler won't even allocate a variable for static const integer values so long as you never attempt to use the address of it.

Upbow answered 25/5, 2010 at 17:28 Comment(0)
R
2
#if defined (__GNUC__)
#  if defined (__cplusplus)
#     define _ASSOCIATIONS_(X) __attribute__((packed))
#  else
#     define _ASSOCIATIONS_(X) __attribute__((packed)) X
#  endif
#else
#  if defined (__cplusplus)
#     define _ASSOCIATIONS_(X)
#  else
#     define _ASSOCIATIONS_(X) X
#  endif
#endif

typdef enum BeNeLux {
  BELGIUM,
  NETHERLANDS,
  LUXEMBURG
} _ASSOCIATIONS_ (BeNeLux);

This seems to compile in my g++ (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)

Rind answered 25/5, 2010 at 16:56 Comment(2)
Hi Meera, it works for us with g++ versions above 4 too. The problem is we have to use version 3.3.5 or lower (above comments).Meadows
I made another try... https://mcmap.net/q/2019865/-c-packing-a-typedef-enum/…Rind
C
1

There are no real breakthroughs here. I just reordered things in the hopes that your compiler would like it better. I did not have your version of gcc or g++ so I could not test with those. I did run it through version 3.4.5 gcc and g++ (mingw special) which both warned 'packed' attribute ignored when ordered like your code, but did not complain about mine.

#ifdef __GNUC__
#define attribute(x) __attribute__((x));
#else
#define attribute(x)
#endif


#ifdef __cplusplus
extern "C" {
#endif

enum BeNeLux
{
    BELGIUM,
    NETHERLANDS,
    LUXEMBURG
} attribute(packed);
// I declared attribute to look like a f() so that it would not look like I was
// declaring a variable here.

#ifndef __cplusplus
typedef enum BeNeLux BeNeLux; // the typedef is separated into a separate stmt
#else
}
#endif
Caul answered 26/5, 2010 at 4:13 Comment(0)
D
0

I suppose you're using GCC and G++. The code compiles fine with either, for me. It would be rather suprising to see such a feature disappear when enabling C++ on any one particular compiler.

Make sure that your #define is not #if'ed out for C++ code, e.g. #ifndef __cplusplus.

Try g++ -E to see the preprocessor output and verify that the #define appears.

Also, even for preprocessor macros, names beginning with an underscore and capital letter or two underscores are reserved for the compiler and library. If you must have a macro, PACKED might be the best name for it.

Derinna answered 7/5, 2010 at 21:18 Comment(3)
Added that code directly without the #ifs and it still did not work.Meadows
@Sagar: try both gcc -v and g++ -v to make sure you're getting the same version of both.Derinna
According to the manual gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_5.html#SEC105 this should work even in GCC 2.95.Derinna
F
0

In C++, you don't need the typedef. Just start with enum BeNeLux. It's also possible (I can never remember) that declaring a type and a variable with the same identifier may not be legal in one of the languages.

Forename answered 7/5, 2010 at 21:41 Comment(2)
the addendum makes clear that's not what he wants. Declaring type and identifier simultaneously is impossible in both languages.Derinna
I mean, declaring typedef and identifier simultaneously is impossible in both.Derinna
T
0
enum BeNeLux
{
   BELGIUM,
   NETHERLANDS,
   LUXEMBURG
};

This is what is expected of C++ code.

Technetium answered 7/5, 2010 at 21:43 Comment(2)
No, it doesn't. If he just used this, then he would be finished.Technetium
No. The question is for "typedef enum" and attribute packing. I know enum BeNeLux would work, but that is not what I need.Meadows
R
0
#if defined (__GNUC__)

#  if defined (__cplusplus)
#     define ENUM enum
#  else
#     define ENUM typedef enum
#  endif

#  if defined (__cplusplus)
#     define _ASSOCIATIONS_(X) __attribute__((packed))
#  else
#     define _ASSOCIATIONS_(X) __attribute__((packed)) X
#  endif
#else
#  if defined (__cplusplus)
#     define _ASSOCIATIONS_(X)
#  else
#     define _ASSOCIATIONS_(X) X
#  endif
#endif

ENUM BeNeLux {
  BELGIUM,
  NETHERLANDS,
  LUXEMBURG
} _ASSOCIATIONS_ (BeNeLux);

Another snippet. see the new #define ENUM

Rind answered 26/5, 2010 at 19:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.