[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Size of NSInteger/NSUInteger/CFIndex
From: |
Richard Frith-Macdonald |
Subject: |
Re: Size of NSInteger/NSUInteger/CFIndex |
Date: |
Wed, 21 Aug 2013 04:59:50 +0100 |
On 20 Aug 2013, at 22:34, Stefan Bidi <address@hidden> wrote:
> I'm re-writing the CoreBase string formatting function (printf with %@
> support) and while going through the printf(), Apple docs and other sources
> on the internet I ran across a potential problem with some of the assumptions
> made when defining these types.
>
> I understand that despite being very portable, GNUstep isn't made to work on
> all platforms, but I'm still going to use an unlikely platform as example...
>
> Anyway, in the Apple docs, they have:
> typedef long NSInteger;
> typedef unsigned long NSUInteger
> typedef long CFIndex;
>
> Yet, the discussion says:
> When building 32-bit applications, NSInteger is a 32-bit integer. A 64-bit
> application treats NSInteger as a 64-bit integer.
From all my reading, I think the line immediately above is closest to a
statement of what the NSInteger/NSUInteger types are for ... to portably
support the situation where you want an integer big enough to store a pointer,
when the memory model may (like LP64) have a default integer size which is not
big enough.
> This is true on LP64 platforms but not on any other platform. The problem
> that I see here is that the Apple docs about string formatting say that if
> you want to format a NSInteger/NSUInteger/CFIndex you should use '%ld' or
> '%lu'.
they also say you have to cast the value to be a long or unsigned long.
I prefer to stick to the posix standard for this and use the PRIdPTR and
PRIuPTR macros.
Both formatting options work, both are ugly :-(
IO find the posix macros a bit uglier, but they do have the advantages of being
a bit shorter than the ld/lu format combined with the cast, and being pretty
explicit about what the argument type actually is.
> GNUstep, on the other hand, defines these values as intptr_t/uintptr_t, which
> in my opinion is wrong. We essentially assume these types are as long as a
> pointer, which is true if you assume LP64. However, this assumption is not
> true for a cross-platform library.
The point about using intptr_t/uintptr_t is precisely that it doesn't assume
that a long is the size of a pointer, so it's a portable declaraction for
NSInteger/NSUInteger.
> Lastly, I was browsing the web and came across this
> (http://www.nongnu.org/avr-libc/user-manual/group__avr__stdint.html) where
> int is 16-bits, long is 32-bits and intptr_t is 16-bits. I realize AVR is
> not a target, but I just wanted to use it as another example where long is
> not equivalent to intptr_t. And who known, someone might want to use it in
> the future.
>
> I would like to suggest typedef'ing NSInteger/NSUInteger/CFIndex as long.
> That way we can correctly format these integers across all platforms
> supported by GNUstep.
I think you are understanding this the wrong way round , because you are
reading the typedefs rather than the documentation. NSInteger and NSUInteger
are not supposed to be 'long', they are supposed to be pointer sized; 32bit an
a 32bit platform and 64bit on a 64bit platform. If you had a 64bit platform
with a 128bit long, NSInteger would be 64bit, not 128bit.