why are u32/uint32_t/SceUInt32 defined as longs?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
snowsquirrel
Posts: 51
Joined: Sun Feb 24, 2008 3:36 am

why are u32/uint32_t/SceUInt32 defined as longs?

Post by snowsquirrel »

Why is u32 defined as an unsigned long int? I know on my 32 bit systems, a long and int are both 32. So it doesn't matter, which is used.... kind of... one really annoying side effect are the compiler warnings generated from printf.

Code: Select all

u32 mynum  = 25L;
printf( "my num %u\n", mynum );
This generates a warning because it wants you to use %ul instead of %u.

I looked at stdint.h on a 32bit and 64bit system and both just used an unsigned int, not an unsigned long.

It bugs me, as I maintain both a PC, and PSP version of my project.

Just wondering if there is a valid reason, or if it is just arbitrary?

~S
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

If I remember well:

a short is always 16bits
a long is always 32bits

and depending on the platform an int is either a short or a long

so if you want to be platform independent u32 has to be an unsigned long
not an unsigned int.
--pspZorba--
NO to K1.5 !
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Uh... no.

A short is 2 bytes.
An int is 2 or 4 bytes, depending on the CPU (always 4 on 32 bit or better CPUs). To be technical, a short int is 2 bytes, while a long int is 4 bytes. "int" is just shorthand for "long int" on most compilers. Note that a "long int" is NOT the same thing as a "long".
A long is 4 or 8 bytes, depending on the CPU.
A long long is 8 bytes.
A pointer is 4 or 8 bytes, depending on the CPU.
bulb
Posts: 50
Joined: Thu Jan 19, 2006 10:59 pm

Post by bulb »

Actually, neither is correct. The size of types in C/C++ are not fixed - the implementation is free to choose whatever size it wants. Hence the use of sizeof. This is what Java and C# "fixed". :)

I once worked with a Z80 compiler that had short defined as 1 byte (8 bits) long, and on one esoteric architecture a short was defined as 12 bits (yes, not all systems use multiples of 8 and not all systems use von Neumann architecture).

As to original poster, I think this was just arbitrary (preference of style). I also like to use long (instead of int) when I want to define 32-bit. You could switch to C++ streams and live without those warnings, because C++ Standard Library is typesafe.
snowsquirrel
Posts: 51
Joined: Sun Feb 24, 2008 3:36 am

Post by snowsquirrel »

Getting o/t here, but I find streams a PITA to use, plus they tend to blow up mem usage on embedded systems.

Printf is probably the only old school technique I continue to employ. I wish they would make modernized version of of it, something like C# version of formatted strings where the format operators are not type specific. Of course that is easy in C# where everything has a toString() method.

~S
ooPo
Site Admin
Posts: 2023
Joined: Sat Jan 17, 2004 9:56 am
Location: Canada
Contact:

Post by ooPo »

http://en.wikipedia.org/wiki/C_variable ... clarations
There is some confusion in novice C programmers as to how big these types are. The standard is specifically vague in this area:

* A short int must not be larger than an int.
* An int must not be larger than a long int.
* A short int must be at least 16 bits long.
* An int must be at least 16 bits long.
* A long int must be at least 32 bits long.
* A long long int must be at least 64 bits long.
It may be vague and seem arbitrary, but in C that's a feature and we like it that way!
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Very true. I just described the majority of 16 / 32 / 64 bit compilers. It's rare that you'll run into anything else, so my post is the most relevant to folks here.
:)
whistler
Posts: 39
Joined: Tue Mar 04, 2008 7:08 am

Post by whistler »

J.F. wrote:Note that a "long int" is NOT the same thing as a "long".
sure it is:) when you use the long modifier on its own the int is implied
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

whistler wrote:
J.F. wrote:Note that a "long int" is NOT the same thing as a "long".
sure it is:) when you use the long modifier on its own the int is implied
Depends on the compiler. There's that "vagueness" that Oopo mentioned. :) The compilers I grew up on, long and long int were two separate types.

I guess seeing what we use here, we should probably stick to whatever gcc uses for the types.
ooPo
Site Admin
Posts: 2023
Joined: Sat Jan 17, 2004 9:56 am
Location: Canada
Contact:

Post by ooPo »

When it comes to C, if it isn't defined specifically in the standard then you should be very careful. That's what we call 'undefined behavior' and there's no reason to count on it being the same on every system, or even on every execution.

Usually I create a types.h file, with defines for things like uint08 and sint32. That way I can change them in one place in the code for whatever platform and compiler I end up using at any given time.
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

Tbh I find that GCC's printf warnings to be somewhat overzelous, they made changes between 4.0 and 4.1 which added more petty warnings, one of them being things like the long int shit. Psplink compiled fine on 4.0.2 with all warnings, on 4.1 it spat out a fair number of format warnings. Annoys me to the extent that I tend to just turn them off, I am only really interested in ones which indicate missing parameters or mismatches %s to pointers. Anything else is generally a display issue/portability issue vs. rather than a potential crash.
hlide
Posts: 739
Joined: Sun Sep 10, 2006 2:31 am

Post by hlide »

ooPo wrote:Usually I create a types.h file, with defines for things like uint08 and sint32. That way I can change them in one place in the code for whatever platform and compiler I end up using at any given time.
I see you insert a 0 to uint8, so I guess you like to have types of same length as possible. :)
Heimdall
Posts: 245
Joined: Thu Nov 10, 2005 1:29 am
Location: Netherlands
Contact:

Post by Heimdall »

Yesterday i picked up the "The C programming language" book from K&R and it states that a int is of the same of the platform default (and atleast 16bits) and a short int (or just short) is atmost 16 bits, and a long int (or just long) is at least always 32 bits. So the newlib definition of uint32_t and int32_t are correct by defining it as a long, however if you want to be picky :) you can hack your newlib includes to your favour. I've tested rebuilding the full compiler + sdk with the -Werror flag on and there are my only changes to make int32_t and uint32_t aliased to int and not long:

stdint.h

on line 37 i replaced the original preprocessor code with:

Code: Select all

/* Check if "long" is 64bit */
#if __STDINT_EXP(LONG_MAX) > 0x7fffffff
#define __have_long64 1
#endif
This removed the automatic __have_long32 definition to be defined thus later on int32_t will be mapped to int and not long

then on my SDK i configured it with:

CFLAGS=-Werror ./configure --with-pspdev=/c/pspsdk

and had only to fix the prof.c file because it warns about a missing and a wrong prototypes, so i replaced line 81 of prof.c with:

Code: Select all

void gprof_cleanup(void);
void __mcount(unsigned int, unsigned int);
and now the SDK builds without warning and errors and int32_t are int. I think that if you want to hack your current setup just edit the stdint.h on your psp/include dir like above and it works, BUT!!! from now on you may have broken the portability of your code...
ooPo
Site Admin
Posts: 2023
Joined: Sat Jan 17, 2004 9:56 am
Location: Canada
Contact:

Post by ooPo »

hlide wrote:I see you insert a 0 to uint8, so I guess you like to have types of same length as possible. :)
It pleases my eye when I see things line up nicely. :)
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Heimdall wrote:Yesterday i picked up the "The C programming language" book from K&R and it states that a int is of the same of the platform default (and atleast 16bits) and a short int (or just short) is atmost 16 bits, and a long int (or just long) is at least always 32 bits. So the newlib definition of uint32_t and int32_t are correct by defining it as a long,
Only on 32 bit systems! On 64 bit systems, long (or long int) is 64 bits.
however if you want to be picky :) you can hack your newlib includes to your favour. I've tested rebuilding the full compiler + sdk with the -Werror flag on and there are my only changes to make int32_t and uint32_t aliased to int and not long:
Did you misspeak above? First you say it's correct to define uint32_t as a long, and now you say you made sure it's aliased to int and NOT long.

I think we need to be clear - on current 32 bit systems, int and long are 32 bits, but on all 64 bit systems, int is 32 and long is 64. So it is NOT correct to alias int32_t/uint32_t to long int as that will fail on all 64 bit systems.

All current gcc versions (the only compiler we care about) alias 32 bit values to int and 64 bit values to long.

Now if you're talking about psp-gcc, you COULD alias int32_t to long since it's compiling for a 32 bit CPU, but the code won't be portable.
Heimdall
Posts: 245
Joined: Thu Nov 10, 2005 1:29 am
Location: Netherlands
Contact:

Post by Heimdall »

i know its not clean, its a hack. but since the psp is 32bits it wouldn't arm to alias int32_t to int. again this is a hack that reduces lots of compiling warnings
snowsquirrel
Posts: 51
Joined: Sun Feb 24, 2008 3:36 am

Post by snowsquirrel »

J.F. wrote: Now if you're talking about psp-gcc, you COULD alias int32_t to long since it's compiling for a 32 bit CPU, but the code won't be portable.
Which was my original point. on 90% (pulled that number out of my ass) of the platforms out there typedefing int32 as int works. While typedefing it as long, only works on32 bit systems.

~S
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

Code: Select all

u32 mynum  = 25L; 
printf( "my num %u\n", mynum ); 
Nonetheless, the only portable version of this code is

Code: Select all

u32 mynum  = 25L; 
printf( "my num %u\n", (unsigned int)mynum ); 
so that's how you make your code correctly portable. There's no portable guarantee that u32 and unsigned int or unsigned long or unsigned long int are the same.

Jim
User avatar
jean
Posts: 489
Joined: Sat Jan 05, 2008 2:44 am

Post by jean »

Apart from portability argumentations, sometimes even procedural coding needs some modelization :) I think of it this way: if i need a type representing a device and i know that there are <255 devices then i could (quick and dirty) choose a char; OR i could define a "device" type as a char and use it instead. Why? Because so i can define functions accepting "device" and not "char" helping me to point out inaccuracies, or (in c++) letting me redefine some operators just to make life more complex.
Post Reply