   Cross Platform Data Types (Pros and Cons)
  Hi allI'm trying to write a large (sometime in the future possibly cross platform) game engine. As stated in this thread "Cross Platform Compatiblity", when planing or writing cross platform code, one should create one's own data types (or use a 3'rd party cross platform library's data types):Quote:Original post by  Anonymous Poster (who's that anyway?)First and foremost make your own data typesEX: typedef int myInt; and use myInt instead of int through out your game. Why? Because ints and other variables can varry in size on different platforms.#ifdef _PSXtypedef Int32 myInt;#endif#ifdef _Win32typedef int myInt;#endifIt's not pretty but it does the job.I don't like using 3'rd party stuff very much, especially at that level, so I'm thinking of writing my own data types, you know, something like "cp_uint32", "cp_sint32", "cp_uint64", etc.My question now is this:Is it really so important to create one's own data types and then use ONLY those EXCLUSIVELY in the ENTIRE project?And what about the trade-offs? Don't own data types make source code A LOT harder to read for other programmers, third parties, etc. because you loose source code highlighting (you know, "int" being printed in blue, own data types not) etc.?Any feedback / experience appreciated!Mark   
  Assume for a moment that you use the built-in types. Can you guarantee that your code will continue to work when you port it to a platform where 'int' is 64- or 16-bit wide?Using your own types sidesteps this issue.There is some small loss in readability but it's not all that bad. For example:int64 foo = 1 << 42;int32 bar = 1 << 31;int16 baz = 42;uint64 foo = 1 << 42;uint32 bar = 1 << 31;uint16 baz = 42;Quite readable, IMO.Many IDEs allow you to specify custom types for syntax highlighting so check whether yours supports that.   ;  No, most of the time I'd just use ints if you want an integer. However, if I'm writing a function that assumes that an integer is 32 bits (e.g. a 32bit string hashing function), I will use a int32 typedef (which is declared in some cross-platform header) instead of an int.   ;  Hey, thanks for the replies!:-)I use Visual Studio 2005 for Windows (now), I'll check if it has self-made syntax highlighting. That would be pretty cool.About using regular ints mostly and own type names only where you know that you need a 32 bit or 64 bit, etc.: Isn't it difficult in practice to know BEFOREHAND for EVERY variable if you'll EVER be using it in a way which requires a certain number of bits?I mean you never know how you might end up using a variable, no?Mark;Quote:Original post by MarkieIsn't it difficult in practice to know BEFOREHAND for EVERY variable if you'll EVER be using it in a way which requires a certain number of bits?Variables aren't chosen because they are pretty. They serve a role.Assuming one is building a container of indexable items. The index variable must be large enough to uniquely index every single entry.If container is made to hold chars, then in 4GB space there can be at most 2^32 unique entries, so 32-bit integer will do. If such container holds bits, then we need 35-bit index.Different CPU architectures prefer differently sized elements. Perhaps due to register sizes, perhaps due to cache alignment or due to third-party API requirements. This must be taken into consideration.When planning for cross-platform software, one first selects target platforms (compiler, OS, standard library, third-party libraries, CPU architectures, memory models, hardware devices).Then a domain model is constructed. What is the high-level functionality, how will the parts of application interact with IO (files, network, APIs). A matrix can be made outlining this functionality.Commonalities are then extracted (such as: int is supported on all platforms, but float isn't). Specifics are then extracted into separate support modules (ifdefed, polymorphism, etc...). Third-party cross-platform libraries must be treated as a platform. No matter what they promise, they will never be a 100% match.Then the design is split between shared and platform-specific parts, and implemented appropriately.For long-term projects, provisions for future extensions can be made, such as how the project will be migrated from 32 to 64 bit application, etc...Or, the simple version: portability is incredibly time consuming and tedious task. Use managed language instead.For comparison, it is estimated that using C# vs. C++ offers 4 times productivity boost. However, each additional platform that needs to be supported doubles the development time in C++. So when supporting 3 platforms, C# gets 32 fold advantage. What takes one day in C#, takes one month in C++.   ;Quote:Original post by MarkieAbout using regular ints mostly and own type names only where you know that you need a 32 bit or 64 bit, etc.: Isn't it difficult in practice to know BEFOREHAND for EVERY variable if you'll EVER be using it in a way which requires a certain number of bits?I mean you never know how you might end up using a variable, no?Not really... Some examples might be, amount of hit points, object IDs, bone IDs within a model, free space left within an inventory, etc... All of these examples (except the object ID one) probably only needs a single byte of storage, but we use int anyway because it's a more natural integer type for the CPU to work with (usually). If we wanted to be uber leet and save some RAM, we could spend time to determine that "health" can fit in a char and "inventory space" can fit in a short, but we're lazy so we just use the general purpose integer type ;)If you're designing a game object system with "object IDs" though, that's one case where you'll probably stop to think how high those numbers can go. Will I have 65k (USHRT_MAX) objects at once? Will I have 4 billion (UINT_MAX) objects at once? Is it ok for this counter to overflow back to 0 if it hits that limit?These questions usually only come up in low-level "game engine" type code though.In day-to-day usage, most of the time "billions" should be enough (billions of health? billions of joints in an animated model? probably not).The other time you actually have to think about this stuff is if you're doing low-level networking packets, where you actually care about saving space (e.g. writing your 0-100 health value into 7 bits only), but in "regular" code, saving space like this wastes to much programming time and CPU time for it to be worthwhile.Quote:Original post by AntheusOr, the simple version: portability is incredibly time consuming and tedious task. Use managed language instead.For comparison, it is estimated that using C# vs. C++ offers 4 times productivity boost. However, each additional platform that needs to be supported doubles the development time in C++. So when supporting 3 platforms, C# gets 32 fold advantage. What takes one day in C#, takes one month in C++.That's a pretty outrageous claim! At work, the engine guys have to write a lot of code once-per-platform, but all of our game-code (C++) is written once and compiles/runs on all the current game consoles... So perhaps your claim is true for the case of writing a portability layer itself, but not for writing software on top of said layer.   