PDA

View Full Version : newbee NSArray




KeithsPuma
Sep 5, 2008, 12:30 PM
Hi
I'm trying to create a NSArray initialized with 32 bit integers
When I try :-

NSArray *p1 = [ [ NSArray alloc ] initWithObjects:
0x0409001F,
0x00000086,0x00000086,0x00000086,0x00000086,
nil ];

I get the following warning :-
"warning: passing argument 1 of 'initWithObjects:' makes pointer from integer without a cast"

What am I doing wrong ?
Thanks
Keith



lee1210
Sep 5, 2008, 12:42 PM
Hi
I'm trying to create a NSArray initialized with 32 bit integers
When I try :-

NSArray *p1 = [ [ NSArray alloc ] initWithObjects:
0x0409001F,
0x00000086,0x00000086,0x00000086,0x00000086,
nil ];

I get the following warning :-
"warning: passing argument 1 of 'initWithObjects:' makes pointer from integer without a cast"

What am I doing wrong ?
Thanks
Keith

From the looks of it, you're not clear on what an object is yet. Essentially what your code is doing is taking all of those hex values, and casting them to NSObject *s. Obviously, that's not what you want to do. The primitives in Objective-C are not objects, so they can't be put into an NSArray without wrapping them. The most common wrapper for most of primitives (the numbers and BOOL) is NSNumber. Look into wrapping your ints using [NSNumber numberWithInt:x], then placing the NSNumbers into your NSArray. Note: almost everything, including NSNumber, inherits from NSObject, so you can "downcast" them implicitly when you see a method that takes an NSObject.

-Lee

KeithsPuma
Sep 5, 2008, 01:31 PM
Thanks Lee
What I was trying to do was the equivalent of
const int p[] = {
0x0409001F,
0x00000086,0x00000086,0x00000086,0x00000086 };

I thought I would try to use NSArray as I'm trying to learn Cocoa.
The examples from the web were initializing the array with @"fred",@"Bert" etc. which I suppose are objects.
I did try and cast the constants with the [ NSNumber numberWithInt:0x0409001F ] as suggested, but since I have 100 arrays with 300 Ints in each the code would look horrible, so in this case I will sick with the "C" code above.
Thanks again
Keith

lee1210
Sep 5, 2008, 01:46 PM
Thanks Lee
What I was trying to do was the equivalent of
const int p[] = {
0x0409001F,
0x00000086,0x00000086,0x00000086,0x00000086 };

I thought I would try to use NSArray as I'm trying to learn Cocoa.
The examples from the web were initializing the array with @"fred",@"Bert" etc. which I suppose are objects.
I did try and cast the constants with the [ NSNumber numberWithInt:0x0409001F ] as suggested, but since I have 100 arrays with 300 Ints in each the code would look horrible, so in this case I will sick with the "C" code above.
Thanks again
Keith

This might be a good opportunity to try out some Obj-C/Cocoaisms. You could call a function that will return an NSArray *, and have it take a C-style int array, and a length, and return an NSArray filled with them. In the function you could just have a loop that wraps an int in an NSNumber, and adds it to the array.

Just an idea, not sure what you're using it for. there will be overhead for 30,000 NSNumber wrappers, though.

-Lee

gnasher729
Sep 5, 2008, 03:02 PM
Hi
I'm trying to create a NSArray initialized with 32 bit integers
When I try :-

NSArray *p1 = [ [ NSArray alloc ] initWithObjects:
0x0409001F,
0x00000086,0x00000086,0x00000086,0x00000086,
nil ];

I get the following warning :-
"warning: passing argument 1 of 'initWithObjects:' makes pointer from integer without a cast"

What am I doing wrong ?
Thanks
Keith

What do you plan to do with this array? Could it be that something like

unsigned int p1 [] = {0x0409001F,
0x00000086,0x00000086,0x00000086,0x00000086 };

could do what you want and be about ten thousand time more efficient?

KeithsPuma
Sep 6, 2008, 02:30 AM
gnasher729
Yes thats what I wanted to do and have decided I will stick with that method, see posing #3 ;)
Back in the day I was one of the programmers who wrote
http://en.wikipedia.org/wiki/Pushover_(video_game)
and as an exercise I thought I would try to write it for the apple mac ( iPhone ? ). It was originally wrote in "C" ( not really done in those days ) and assembly.
So that data that is in the arrays is the puzzle data consisting (byte) background, (byte) Platform Overlay, (byte) Domino and (byte) ladder.
These are pointers to graphics that need to be masked with each other to create the background. ( layers ).
There are 20 blocks across and 15 blocks down hence 300 integers per puzzle and 100 puzzles.
Hope that answers your and Lee's questions.

No doubt I will have more question as I get stuck with my project I will be posting here as the people are very kind and friendly.

PS ( Gnasher ) I like reading the Dandy/Beano when I was a kid.

lee1210
Sep 6, 2008, 10:07 AM
gnasher729
Yes thats what I wanted to do and have decided I will stick with that method, see posing #3 ;)
Back in the day I was one of the programmers who wrote
http://en.wikipedia.org/wiki/Pushover_(video_game)
and as an exercise I thought I would try to write it for the apple mac ( iPhone ? ). It was originally wrote in "C" ( not really done in those days ) and assembly.
So that data that is in the arrays is the puzzle data consisting (byte) background, (byte) Platform Overlay, (byte) Domino and (byte) ladder.
These are pointers to graphics that need to be masked with each other to create the background. ( layers ).
There are 20 blocks across and 15 blocks down hence 300 integers per puzzle and 100 puzzles.
Hope that answers your and Lee's questions.

No doubt I will have more question as I get stuck with my project I will be posting here as the people are very kind and friendly.

PS ( Gnasher ) I like reading the Dandy/Beano when I was a kid.

It seems to me (though I may misunderstand the architecture) that you only need to have one "level" at a time loaded in memory. This changes the amount of overhead that would be necessary to store these values in objects by a large margin. It may still be simpler for you to just keep these in C style int arrays, but having an NSArray of 300 NSNumber objects is a lot less overhead than 30,000. You're spending 1204 or 1208 bytes now for 300 ints and one int pointer(which may be 4 or 8 bytes). I can't say how big (or if it's even the same instance to instance) an NSNumber is, but you'd be looking at:
4 or 8 bytes for your NSArray *
The size of the backing store for the NSArray and other Object overhead. I have no idea what this is, but since it is immutable it's probably just a regular C-style array, so this would probably just be a NSObject *, so again 4 or 8 bytes for the backing store, plus an unknown (to me at least) Object overhead.
300 NSNumber *s, 4 or 8 bytes each, so either 1200 or 2400 bytes here
300 NSNumber Objects. I have no idea how big these are. I think the backing store would only be 8 bytes at most, because the largest values it can take are doubles and long longs. So that's 2400 bytes, plus Object overhead. This is a shot in the dark.

So this gives us:
4 or 8
+
4 or 8 + N (NSArray overhead)
+
1200 or 2400
+
2400 + 300 M(NSNumber overhead)

So being modest and saying that the NSArray and NSNumber overhead is 32 bytes, that gives us:
13,240 bytes on a system with 32-bit pointers
or
14,448 bytes on a system with 64-bit pointers

This is about an 11-12x increase in memory, and probably somewhat of a hit in setting it up (about 0 with int arrays, since you have them in your data section already, and you're just assigning a pointer, versus 300 NSNumber initializations, and one NSArray initialization).

In this particular case it sounds like you get no real benefit from having an NSArray, since you know the exact length of the array all the time already, etc.

On a separate note, you will have to be careful about getting your individual bytes out of your ints. I would actually say to just have 4 different character arrays that store your data, rather than 1 int array. I don't know if you plan to support x86, PPC, and ARM, but PPC is big-endian and x86 and the ARM in the iPhone are little-endian. This will make getting your bytes out of your int a more difficult task, if you're going to support both. If you had 4 character arrays, it would be a lot easier to handle. Just a thought.

-Lee

KeithsPuma
Sep 6, 2008, 10:53 AM
Lee
const int puzzles[] = {
// StartH:StartV:Min:Sec
// Ladder:Domino:Ledge:Background, ... etc 20 across by 15 Down

// puzzle1
0x0409001F,
0x00000086,0x00000086,0x00000086,0x00000086,....(301 int's per puzzle )
// puzzle2
0x0409001F,
0x00000086,0x00000086,0x00000086,0x00000086,....
....
// puzzle100
0x0409001F,
0x00000086,0x00000086,0x00000086,0x00000086,....};

void Test()
{
int StartH, StartV, Min, Sec;
int Ladder, Domino, Ledge, Background;
int x, y;
int PuzzleNumber;

PuzzleNumber = 99;
Sec = ( puzzles[ ( PuzzleNumber - 1 ) * 301 ] & 0x000000FF ) >> 0;
Min = ( puzzles[ ( PuzzleNumber - 1 ) * 301 ] & 0x0000FF00 ) >> 8;
StartV = ( puzzles[ ( PuzzleNumber - 1 ) * 301 ] & 0x00FF0000 ) >> 16;
StartH = ( puzzles[ ( PuzzleNumber - 1 ) * 301 ] & 0xFF000000 ) >> 24;
printf( "Puzzle Number %02d\n", PuzzleNumber );
printf( "%s %02d:%02d\n", "Time = ", Min, Sec );
printf( "%s %02d,%02d\n", "Pos = ", StartH, StartV );

for ( y=0; y<15; y++ )
{
for ( x=0; x<20; x++ )
{
Background = ( puzzles[ ( 1 + ( PuzzleNumber - 1 ) * 301 ) + ( y * 20 ) + x ] & 0x000000FF ) >> 0;
Ledge = ( puzzles[ ( 1 + ( PuzzleNumber - 1 ) * 301 ) + ( y * 20 ) + x ] & 0x0000FF00 ) >> 8;
Domino = ( puzzles[ ( 1 + ( PuzzleNumber - 1 ) * 301 ) + ( y * 20 ) + x ] & 0x00FF0000 ) >> 16;
Ladder = ( puzzles[ ( 1 + ( PuzzleNumber - 1 ) * 301 ) + ( y * 20 ) + x ] & 0xFF000000 ) >> 24;
printf( "%02d,%02d %02X %02X %02X %02X\n", x + 1, y + 1, Background, Ledge, Domino, Ladder );
}
}


Seems to work as expected on an iPhone.
When I 1st wrote pushover I did the Amiga/Atari ST versions running on motorola 68000 while my friends did the PC version ( intel ), so I have experience with mixed type programming.
The reason I tried to use NSArray is that its what I thought I was supposed to use. I could put each puzzle in a file and load when required but on an iPhone I would not gain anything there.
What I now am trying to work out is that the background is made up of graphic 20x15 blocks of ( originally 16x16 pixels ) taken from a single picture. I will work out the area of the picture I want ( from the above data ) then place it on the screen where I want it, wish me luck.
I've made a mockup of what I'm trying to achive.
http://www.iPushover.com

Thanks Keith

lee1210
Sep 6, 2008, 11:21 AM
Seems to work as expected on an iPhone.
When I 1st wrote pushover I did the Amiga/Atari ST versions running on motorola 68000 while my friends did the PC version ( intel ), so I have experience with mixed type programming.

Good, then. Just something to watch out for if you also want to target PPC macs. If you're just gunning for the iPhone it's not an issue.


The reason I tried to use NSArray is that its what I thought I was supposed to use.

There are definite advantages to using NS(Mutable)Arrays, but none of them may be relevant here. Some reasons off the top of my head:
Interacting with Cocoa API calls - Almost all of these will expect NSArrays, NSStrings, NSNumbers, etc. There are definitely things (mostly Core things instead of Cocoa) that deal with NSUInteger, NSInteger, etc. that are basically just unsigned ints, ints, etc. but allow for widths appropriate to the bit-width of the chip. However, most of the time if you need to pass a list of something to an API method, it's with an NSArray.

If you're starting from scratch and you'll need access to some of the convenience methods provided by NSArray ( makeObjectsPerformSelector:, indexOfObjectIdenticalTo:inRange:,- count) that you don't want to code yourself against C-style arrays.

If you're using objects descended from NSObject - This is more personal style, you certainly can make a C-style array of NSObject *s, but I would consider it better form to just use an NS(Mutable)Array for objects.

I'm sure there are other compelling reasons as well, but if you're using primitives, especially with existing algorithms, or you're really starved for memory/speed, there's certainly reasons to stick with C-style arrays.


I could put each puzzle in a file and load when required but on an iPhone I would not gain anything there.


Why not? The iPhone still has separate RAM and "disk". They aren't pooled like some other devices. Even if you stuck with C-Style arrays you'd only need 1,200 bytes per board in memory at a time, instead of 120,000 bytes. I guess even for the iPhone this isn't a great savings, but I would be more inclined to load puzzles "on-demand" if you moved to NSArray/NSNumber. Each puzzle would be using ~14,000 bytes at that point, which is still much less than 120,000. I was thinking if you were going to change the code to use NSArray and NSNumber anyway, you could offset the overhead by tweaking the program to load a puzzle at a time.


What I now am trying to work out is that the background is made up of graphic 20x15 blocks of ( originally 16x16 pixels ) taken from a single picture. I will work out the area of the picture I want ( from the above data ) then place it on the screen where I want it, wish me luck.
I've made a mockup of what I'm trying to achive.
http://www.iPushover.com

Thanks Keith

Good luck! i'll be interested to see how it goes.

-Lee