Game Development Community

Why 'S32' instead of 'int', etc?

by Steven Peterson · in Torque Game Engine · 02/16/2006 (11:50 am) · 16 replies

Yet another question...

Why do I see "types" like 'S32', 'U32', and 'F32' used instead of 'int', 'float' and 'double' throughout Torque. I've never heard of these before in general, is this simply a torque convention? And what is the advantage to adopting this convention instead of using standard variable types?

I saw this page: http://www.garagegames.com/docs/tge/engine/types_8h.php
but i'm still not entirely sure what to use when, or why...

Thanks,
Raven

#1
02/16/2006 (12:00 pm)
I believe it's because it's a cross platform app. Each operating system stores their numbers a little differenty. But I could be wrong.
#2
02/16/2006 (12:19 pm)
With my marginal programming experience i would say that, S32 are used if you need to be able to store negative or positive values and U32 are for only positive ... Signed and unsigned. Obviously U32 would be smaller... faster, if I am correct.

I am also farily certain that they are used for cross platform compatability
#3
02/16/2006 (12:29 pm)
Standard C/C++ has types for signed and unsigned as well-
int signedInteger;
unsigned int unsignedInteger;

i'm curious too, tho, what U32 and S32 get you which the standards don't:

types.h:
typedef signed int         S32;     ///< Compiler independent Signed 32-bit integer
typedef unsigned int       U32;     ///< Compiler independent Unsigned 32-bit integer


edit:
i thought the reasoning would be to get consistent bit-length for these basic types,
but i don't see how those typedefs would effect that.

.. unless "signed" and "unsigned" force 32 bits.
#4
02/16/2006 (12:42 pm)
Neil is right. This is done because of cross-platform considerations. A double or an int may have a certain size on one platform, but be completely different on another! For instance, on one particular DSP that I've worked with (TI TMS320C6414 DSP for the curious), a long was 40-bits wide.

By labeling a type a U32, you can be assured that no matter what platform you are on, the U32 is really an unsigned 32-bit (4 byte) value and not something else. This can be accomplished by checking the size limits in a platform's and then typedef'ing to the appropriate types.
#5
02/16/2006 (12:53 pm)
I'm learning as I go (as always :-) but I'm in the same boat as you guys:

It seems the purpose is to force fixed/constant variable lengths and functionality cross-platform even though I also do not see how this is accomplished. Does anyone know for sure? (wonders if this is how urban-legends get started...)

I've also determined the following - maybe this will help others - PLEASE correct me if i'm wrong:

U8 = unsinged 'small int'
U16 = unsigned 'int'
U32 = unsigned 'long int' or 'double'
U64 = unsigned 'long long int'

S8 = singed 'small int'
S16 = signed 'int'
S32 = signed 'long int' or 'double'
S64 = signed 'long long int'

F8 = float (8-bit)
F16 = float ( 16-bit)
F32 = float ( 32-bit)
F64 = float ( 64-bit)

other?

[edit]
Thanks Andrew for clairifying! I think our posts crossed in the mail so-to-speak. :-P
[/edit]
#6
02/16/2006 (12:59 pm)
Here is an example on how to guarantee your type lengths:

#include <limits.h>

...

#if UINT_MAX == 4294967295U
typedef unsigned int u32;       //!< Unsigned int, 4 byte
#elif UINT_MAX = 65535U
typedef unsigned int u16;       //!< Unsigned int, 2 byte
#error Unexpected UINT_MAX.
#endif

...
#7
02/16/2006 (1:01 pm)
@Andrew -
Quote:
By labeling a type a U32, you can be assured that no matter what platform you are on, the U32 is really an unsigned 32-bit (4 byte) value and not something else.

can you explain how this is acheived via the typedefs in platform/types.h ? are U32 and S32 special symbols ?
#8
02/16/2006 (1:03 pm)
Orion: See post above. :)
#9
02/16/2006 (1:03 pm)
.. this second post of yours makes sense to me, yes.

.. oh i guess they have a different types.h for each platform.

i don't think they're checking UINT_MAX tho.

edit: heh. this thread is too hot to handle !
#10
02/16/2006 (1:13 pm)
@ Orion. That's right. Each silicon and/or compiler vendor should ship a limits.h file with their C/C++ SDK/compiler.

GG might not be checking UINT_MAX - I do not have the TGE code in front of me at the moment. If not, they should. :)
#11
02/16/2006 (1:14 pm)
Quote:
edit: heh. this thread is too hot to handle !

I guess so - every once in a while I write a winner.. ;-)

Quote:
This can be accomplished by checking the size limits in a platform's and then typedef'ing to the appropriate types.

And, to my further understanding, this has already been done for us in Torque, so all I have to do is use the new types (S16, U16 and F16, etc). However, it seems a good trick to remember for future projects. That pretty much sum it up?

Thanks all!
Raven
#12
02/16/2006 (4:01 pm)
Typedefs are a C++ construct ... they allow to create new types from existing ones. So in some sort they create an Alias for a built in type.

typedef unsigned int     U32                            // U32 is now known and it is an unsigned int
typedef unsigned int*   pU32                          // pU32 is now known and it is a pointer to an unsigned int
typedef unsigned int     BigU32Array[2000]    // BigU32 is now known and it is a Array of U32 with 2000 items

// you can now do this here
U32 MyInt;
pU32 MyIntPointer;
BigU32Array MyArray;

one example why you need those for cross compiler and cross platform compability is that if you write an int to a file. For 64 bit compilers an int is 64 bits while on normal 32 bit platforms its 32 bits AFAIK. So if you write an int to a file with a 32 bit version of your game it would write 4 bytes. Now if you read this file with your 64 bit version of your game it now would read 8 bytes from that file to fill one int structure. So either you will try to read over the files bounds (if this file is only that one int) or you will read completely false data since you also read the next int. Torque uses streams to pack data to be sent over the net. if the other client doesnt know exactly how big a specific piece of data is he couldnt unpack the data correctly again.
#13
02/16/2006 (4:14 pm)
@ Florian -
right, but what i don't see is why the following line guarantees that U32 will be 4 bytes and not 8:
typedef unsigned int U32;

I think you need some other piece to the puzzle to check what size unsigned int is,
which is i think what Andrew was saying.
#14
02/17/2006 (4:46 am)
It doesnt do that alone but the programmer can controll it:

some example (not sure if microsofts 64 compiler really does make int 64 bits but i'll just assume it here)
#ifdef WIN64
typedef unsigned short U32; // is 4 bytes on 64 bit platforms 
#else
typedef unsigned int U32; // is 4 bytes on 32 bit platforms
#endif

this way you can safely use U32 and be sure that it is 32 bits because you (as the programmer) explicitly set it so :)
#15
02/17/2006 (10:34 am)
Roger, thanks.
#16
02/17/2006 (4:40 pm)
One thing to keep in mind is that even if there aren't any differences in how the numbers are stored among the currently supported platforms, Torque was written to be very portable among *any* platform. By using the built-in types (U32, S32, F32, U16, etc.) in the rest of the engine code you minimize the porting work for a new platform to just creating a new types.h instead of having to go change hundreds of thousands of references to "int".