|
|
| sizeof(enum) -- Is it portable? |
|
Ashteth
Member #3,310
March 2003
|
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
|
You should never, EVER fwrite a struct to begin with. -- |
|
23yrold3yrold
Member #1,134
March 2001
|
Right. Always do it member by member. -- |
|
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 |
|
Ron Ofir
Member #2,357
May 2002
|
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
|
why do you say to not fwrite a struct? [FMC Studios] - [Caries Field] - [Ctris] - [Pman] - [Chess for allegroites] |
|
X-G
Member #856
December 2000
|
Both Peitz and Lenny are wrong here, I'd say. 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. -- |
|
23yrold3yrold
Member #1,134
March 2001
|
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. -- |
|
Bob
Free Market Evangelist
September 2000
|
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: Of course, if you can live with those restraints, then writing a struct/class to a file may be a good idea. -- |
|
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
|
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 |
|
Evert
Member #794
November 2000
|
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. |
|
|