9

Now there is an iPhone coming with 64-bit architecture. long becomes 64 bits (while int remains 32-bit) , and everywhere NSInteger has been used is now a long and so 64-bits not 32. And twitter has quite a few people saying "I'm glad I've used NSInteger everywhere not int".

If you need to store a value that doesn't exceed 32 bits (for example in a loop which only loops 25 times), why should a long be used, because the 32 (at least) upper bits are going to be empty.

If the program has worked on 32-bit integers, then what benefit does using 64-bits for integers provide, when it uses up more memory?

Also there will be situations where using a 64-bit integer gives a different result to using a 32-bit integer. So if you use NSInteger then something may work on an iPhone 5S but not on an older device, whereas if int or long is explicitly used then the result will be the same on any device.

Jonathan.
  • 53,997
  • 54
  • 186
  • 290

3 Answers3

1

If you need to store a value that doesn't exceed 32 bits... why should a long be used?

If you can really make that guarantee, then there is absolutely no reason to value a 64 bit type over a 32 bit one. For simple operations like bounded loops, counters, and general arithmetic, 32-bit integers suffice. But for more complex operations, especially those required of high-performance applications - such as those that perform audio or image processing - the increase in the amount of data the processor can handle in 64 bit modes is significant.

If the program has worked on 32-bit integers, then what benefit does using 64-bits for integers provide, when it uses up more memory?

You make using more memory seem like a bad thing. By doubling the size of some data types, they can be addressed to more places in memory, and the more memory that can be addressed, the less time the OS spends loading code. In addition, having twice the amount of lanes for data in a processor bus equates to an order of magnitude more values that can be processed in a single go, and the increase in register size means an order of magnitude more data can be kept around in one register. This equates to, in simplest terms, a nearly automatic doubling of the speed of most applications.

Also there will be situations where using a 64-bit integer gives a different result to using a 32-bit integer? ...

Yes, but not in the way you'd think. 32-bit data types and operations as well as 64-bit operations (most simulated in software, or by special hardware or opcodes in 32-bit hosts) are "relatively stable" in terms of their sizes. You cannot make nearly as many guarantees on a 64-bit architecture because different compilers implement different versions of 64-bit data types (see LP64, SILP64, and LLP64). Practically, this means casting a 64 bit type to a 32-bit type - say a pointer to an int - is guaranteed to lead to information loss, but casting between two data types that are guaranteed to be 64 bits - a pointer and a long on LP64 - is acceptable. ARM is usually compiled using LP64 (all ints are 32-bit, all longs are 64-bit). Again, most developers should not be affected by the switch, but when you start dealing with arbitrarily large numbers that you try to store in integers, then precision becomes an issue.

For that reason, I'd recommend using NSUInteger and NSInteger in public interfaces, and APIs where there is no inherent bounds checking or overflow guards. For example, a TableView requests an NSUInteger amount of data not because it's worried about 32 and 64 bit data structures, but because it can make no guarantees about the architecture upon which it's compiled. Apple's attempt to make architecture-independent data types is actually a bit of a luxury, considering how little work you have to do to get your code to compile and "just work" in both architectures.

CodaFi
  • 43,043
  • 8
  • 107
  • 153
  • 1
    Your second answer "you make using more memory seem like a bad thing" is exactly the kind of answer I've been looking for. Unfortunately, since I don't have a computer science background, it sailed completely over my head. Is there an example you can give that shows how storing the number "3" in a 64-bit space actually speeds up the app? I agree with Jonathan that it just seems like a huge waste of space and horribly inefficient. – Justin Whitney Feb 09 '14 at 19:06
  • It's all the same `MOV` instruction. It's not arbitrarily small operations that cause the speedup, it's the amount of data that can flow along the processor's busses that makes the difference. It's akin to having a 4 lane highway instead of just 2, then trying to hold a monster truck rally. You can fit more of the smaller data (like normal cars), and squeeze in those big trucks without having to resort to chopping the data up and running it in sequence. – CodaFi Feb 09 '14 at 19:40
  • 1
    Ah good, analogies. I like that. So using your analogy, isn't using a `long` for a small number a bit like driving a massive bus with only 1 forlorn little kid in back? It takes up the same amount of space as a packed bus, but that additional space is wasted. (On second thought, maybe the metaphor is confusing me.) I feel like I'm not grasping something really basic, but it seems that even if it's all the same `MOV` instruction, `MOV`ing a value stored in a 64-bit space would take twice as long as one stored in a 32-bit space? – Justin Whitney Feb 09 '14 at 19:51
  • Nope. `MOV` doesn't take "twice as long" because it copies the receiver (it executes in generally one cycle). And you have to understand that 64-bit integers are allocated on the stack, which means that space is reclaimed when the function exits, or even sooner with a smart enough compiler. Sure you could be economical about what you place on the stack, but you have to be careful in what situations you decide to pare down your value types. e.g. You can use an `unsigned char` for short loops, but why would you care unless you were in a constrained environment? – CodaFi Feb 09 '14 at 19:56
  • 1
    I'm going to have to re-read this a few times. Hopefully it'll begin to sink in. I understand that the space is deallocated when the function exits, but I was particularly thinking about properties that stay around for awhile. In any case, thank you for your patience and explanations. – Justin Whitney Feb 09 '14 at 20:28
-1

The internal storage for NSInteger can be one of many different backing types, which is why you can use it everywhere and do not need to worry about it, which is the whole point of it.

ExitToShell
  • 460
  • 4
  • 14
-1

Apple takes care for backward compatibility if your app is running on a 32 or 64 bit engine and will convert your variable behind the scenes to a proper data type using the __LP64__ macro.

#if __LP64__ 
    typedef long NSInteger; 
    typedef unsigned long NSUInteger; 
#else 
    typedef int NSInteger; 
    typedef unsigned int NSUInteger; 
#endif 
XcodeJunkie
  • 424
  • 4
  • 10
  • NSInteger gives you always the "biggest" possible integer data type accessible in your OS - before and after iOS7. And this macro just takes care for your os version. You're always encouraged to use the "smallest" data type which makes sense for your specific problem. You surely 'can' store a boolean in a 32 bit integer as well in a 64 bit - before and after iOS7. – XcodeJunkie Sep 11 '13 at 20:48