Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » sizeof(enum) -- Is it portable?

This thread is locked; no one can reply to it. rss feed Print
sizeof(enum) -- Is it portable?
Ashteth
Member #3,310
March 2003
avatar

If I use sizeof() for a binary read/write of an enumerated type variable, is this going to cause me problems with cross-platform compatibility? Specifically, does GCC implement this consistently on different platforms?

P.S. I am fully aware that I could cast the variable as an integer, but I'm doing a lazy IO like this:

fwrite(reinterpret_cast<char*>(this), sizeof(struct));

Which writes the struct as a single binary chunk.

X-G
Member #856
December 2000
avatar

You should never, EVER fwrite a struct to begin with.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

23yrold3yrold
Member #1,134
March 2001
avatar

Right. Always do it member by member.

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

gillius
Member #119
April 2000

That still doesn't solve his enum problem, and no, it will not be done the same way on all systems, perhaps. GCC might do it the same way though. The Win32 API's enums have a FORCE_DWORD enum, and they define it like so:

enum MyEnum {
  value = 0,
  value2 = 1,
  //etc
  FORCE_DWORD = 0xFFFFFFFF
};

Or something like that. That would make sure it is DWORD-sized or bigger I'd think, and not the size of a DWORD.

Really you can't rely on sizeof(int) being the same and such. This is one of the things that suck about C++. You could try using some of the C99 types if your compiler supports them (I think Boost provides a wrapper for compilers that don't support it). And I believe some of the C99 types guarantee a variable of an exact size.

Gillius
Gillius's Programming -- https://gillius.org/

Ron Ofir
Member #2,357
May 2002
avatar

Johan peitz fwrites structs, and spellcaster considers fwriting structs a coding gem.

Boost has int<num_of_bits>_t types which provide cross-platform sizes and there's some header for C, maybe stdint.h, can't remember.

FMC
Member #4,431
March 2004
avatar

why do you say to not fwrite a struct?
i think that its one of the fastest way to write down a complicated data sequence

[FMC Studios] - [Caries Field] - [Ctris] - [Pman] - [Chess for allegroites]
Written laws are like spiders' webs, and will, like them, only entangle and hold the poor and weak, while the rich and powerful will easily break through them. -Anacharsis
Twenty years from now you will be more disappointed by the things that you didn't do than by the ones you did do. So throw off the bowlines. Sail away from the safe harbor. Catch the trade winds in your sails. Explore. Dream. Discover. -Mark Twain

X-G
Member #856
December 2000
avatar

Both Peitz and Lenny are wrong here, I'd say. :P

And as for your reasons why you would not want to ... every compiler and platform might use different schemes for 1) Endianness 2) Struct padding/alignment 3) Type sizes, and thus you can't guarantee that fwritten struct data will be compatible across compilers/platforms.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

23yrold3yrold
Member #1,134
March 2001
avatar

If you try compiling your program with another compiler (or different version of your current compiler), you'd better hope and pray those variables are the same size, use the same padding, etc. Otherwise, you're boned. Member by member is much safer. Slower, but safer.

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Bob
Free Market Evangelist
September 2000
avatar

Quote:

Johan peitz fwrites structs, and spellcaster considers fwriting structs a coding gem.

Wirting structs to disk isn't disallowed, or illegal, or undefined. It's usually bad practice because most people doing it aren't aware of the consequences.

If you read/write structs to disk, you can no longer:
- Change compiler options
- Change compiler
- Change the struct or class in any way.
- Use pointers in that struct/class
- Use inheritence on that struct/class
- Use polymorphism on that struct/class
- Port files to other platforms.

Of course, if you can live with those restraints, then writing a struct/class to a file may be a good idea.

--
- Bob
[ -- All my signature links are 404 -- ]

orz
Member #565
August 2000

It is the fastest way to write down a complicated structure. Sometimes it's also the only practical way to do so.

It happens to also be really nasty in C / C++:

a. The sizes of primitive items within a struct vary depending upon your platform, so files produced this way can't be shared across platform boundaries

b. On some platforms the compiler may add invisible "padding" bytes to your structures... this can reduce efficiency, and result in a lack or portability similar to sizes of primitives issue.

c. There tends to be endianness portability issues if you use any primitives larger than 1 byte.

d. If your struct contains pointers... well... you'll have to handle that specially of course.

e. If you're using C++ and your struct has a virtual method or somesuch, then the type data (vtable pointer) will be included as well, but it may result in nasty nasty stuff: the correct value might not even be portable between different runs on the same computer using the same compiler.

All that said, if you insulate your types by defining intermediates ala SDLs Uint32, C99s uint32_t or whatever, and you're carefully about alignment issues, and you don't use anything virtual, and you handle the endianness issues somehow, it IS possible to write fairly portable code that does raw fwrites with structs.

Ashteth
Member #3,310
March 2003
avatar

Thanks for the input guys. Currently my game architecture uses C++ style classes with parallel packed c style structs for IO. This design works really well in combination with overloaded assignment operators. But as was pointed out, be careful:)

I forgot that endian issues may effect enums (if they're stored and presumably written as DWORDs), so perhaps I had best convert my enums to int64s. I don't like doing 200 casts, but if I don't it will probably come back to haunt me sometime. BTW, thanks Gillus for the Boost C99 types wrapper idea. I'll definitely look into using those.

gillius
Member #119
April 2000

I don't know why you would cast to 64-bit integers. That's pretty excessive for an enum. Depending on your enum you should be able to cast to unsigned char or unsigned short?

Gillius
Gillius's Programming -- https://gillius.org/

Evert
Member #794
November 2000
avatar

Quote:

I forgot that endian issues may effect enums (if they're stored and presumably written as DWORDs), so perhaps I had best convert my enums to int64s.

Which, apart from the insane memory usage, will not solve your endianesse problem.
Use Allegro's packfile functions for writing portable files (because you need to specify endianesse anyway).

Go to: