Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > arrays, pointers, and malloc

arrays, pointers, and malloc
Thread Tools
arcticmac
Dedicated MacNNer
Join Date: Apr 2004
Status: Offline
Reply With Quote
Jul 29, 2005, 12:16 AM
 
so, um... (by the way, thanks to all those who replied in my other recent messate).

Anyway, I'm working on some code (objective-c), but it has to do quite a lot of repetitions, and really doesn't need the extra overhead provieded by NSArray... nice for fancy stuff, but this is just storing stuff and getting it back, but I want it to be fast, cause it has to access the arrays roughly a few billion times in the average run, more when being more complex.

So, I have an array, which I want to have three dimensions. the catch is that I don't know what those dimensions are until the user runs a function. (that is, I don't know them at compile time)

I defined my array as follows in my Controller.h:
Code:
short *demoArrays;
In the function that initializes it for me, I do:
Code:
demoArrays = calloc(1, (int)sizeof(short[x][y][z]));
My father informs me that the above SHOULD NOT work and I should do this instead:
Code:
demoArrays = calloc(1, (int)sizeof(short)*x*y*z);
but I tried printing out the "sizeof" thing, and it worked just fine my way, so, for now, that's staying.

Now, here's the problem... when I go to access my array, like so:
Code:
demoArrays[demoStep-1][i][j]
the compiler generates an error:
Code:
Controller.m:180: subscripted value is neither array nor pointer
Can anyone tell me what's up?
     
Detrius
Professional Poster
Join Date: Apr 2001
Location: Asheville, NC
Status: Offline
Reply With Quote
Jul 29, 2005, 12:28 AM
 
Recommendations:

1 - use Objective-C++ so that you can use C++'s new and delete functions.

2 - don't attempt to initialize multi-dimensional arrays in one command. If you need a three dimensional array, you will need to:

Code:
short *** array = new short ** [x]; for(int i=0; i<x; i++) { array[x] = new short * [y]; for(int j=0; j<y; j++) { array[x][y] = new short [z]; for(int k=0; k<z; k++) { array[x][y][z] = /* some value */; } } }
Note that this code hasn't been compiled, and it's been a while since I've done this. I think this is about right. You may also need to make it a one dimensional array and calculate the location by hand from x,y, and z.

As written, your access to array[i][j][k] can't work, because the compiler has no idea what the dimensions of the array are. As far as it's concerned, you asked for a one dimensional array.
( Last edited by Detrius; Jul 29, 2005 at 12:35 AM. )
ACSA 10.4/10.3, ACTC 10.3, ACHDS 10.3
     
arcticmac  (op)
Dedicated MacNNer
Join Date: Apr 2004
Status: Offline
Reply With Quote
Jul 29, 2005, 12:39 AM
 
your code doesn't look right... I think it should be
[code]array[i] = new short * [y];[code] or something like that.

in any case, I tried defining it in the header as
Code:
short ***anArray;
and at least now it compiles, even if I do have to figure out why it still crashes...
     
smeger
Mac Elite
Join Date: Sep 2000
Location: Tempe, AZ
Status: Offline
Reply With Quote
Jul 29, 2005, 02:19 AM
 
In C, an array is just a pointer to a block of memory. A two-dimensional array is a pointer to a block of memory. That block of memory contains a bunch of pointers to other blocks of memory. That's why you can't do it all in one step.

I'd do this (which probably looks nicer with proper tabification):
Code:
int xIndex, yIndex; short ***demoArrays; demoArray = (short ***)calloc( x, sizeof(short **) ); if ( demoArray ) { for ( xIndex = 0; xIndex < x; ++xIndex ) { demoArray[xIndex] = (short **)calloc( y, sizeof(short *) ); if ( demoArray[xIndex] ) { for ( yIndex = 0; yIndex < y; ++yIndex ) { demoArray[xIndex][yIndex] = (short *)calloc( z, sizeof(short) ); } } } }
Geekspiff - generating spiffdiddlee software since before you began paying attention.
     
arcticmac  (op)
Dedicated MacNNer
Join Date: Apr 2004
Status: Offline
Reply With Quote
Jul 29, 2005, 09:03 AM
 
Originally Posted by smeger
In C, an array is just a pointer to a block of memory. A two-dimensional array is a pointer to a block of memory. That block of memory contains a bunch of pointers to other blocks of memory. That's why you can't do it all in one step.
I slept on it, and decided I'd have to do what you suggested. thanks for writing the code for me.

when I free that, I assume I have to do a loop and free everything that i called calloc for, right?
     
Detrius
Professional Poster
Join Date: Apr 2001
Location: Asheville, NC
Status: Offline
Reply With Quote
Jul 29, 2005, 11:06 AM
 
Originally Posted by arcticmac
I slept on it, and decided I'd have to do what you suggested. thanks for writing the code for me.

when I free that, I assume I have to do a loop and free everything that i called calloc for, right?
yup. It's not going to recurse for you--that's your responsibility.
ACSA 10.4/10.3, ACTC 10.3, ACHDS 10.3
     
Detrius
Professional Poster
Join Date: Apr 2001
Location: Asheville, NC
Status: Offline
Reply With Quote
Jul 29, 2005, 11:11 AM
 
Originally Posted by arcticmac
your code doesn't look right... I think it should be
[code]array[i] = new short * [y];[code] or something like that.

in any case, I tried defining it in the header as
Code:
short ***anArray;
and at least now it compiles, even if I do have to figure out why it still crashes...
Oh crap--you're right. You should use the i,j, and k to point to locations in the array--not the x,y, and z. Oops.
ACSA 10.4/10.3, ACTC 10.3, ACHDS 10.3
     
arcticmac  (op)
Dedicated MacNNer
Join Date: Apr 2004
Status: Offline
Reply With Quote
Jul 29, 2005, 12:01 PM
 
Sweet... it compiles now, and it works (i.e. no memory error, although it looks like I've got some other troubleshooting to do to make it do what I want...)

Anyway, I have a second, somewhat related question... here goes.

Say I have another three dimentional array that's similar in style which I want to be able to add items (i.e. 2-d arrays) to (and remove items from as well). my thought would be a method something like this:

Code:
-(void)addSourceArray:(short** arrayToAdd) { int i; short *** tempArray = calloc(srcs+1,sizeof(short **)); //srcs is the number of items in the original 3d array //We'll call the 3d array (which is a class variable) sourceArray for (i=0; i<srcs; i++) { tempArray[i] = sourceArray[i]; } tempArray[srcs]=arrayToAdd; free(sourceArray); sourceArray = tempArray;
So, um... how's that look? and how about this for taking an array off the end:

Code:
-(void)removeLastSourceArray { int i; short ***tempArray = calloc(--srcs, sizeof(short**); for (i=0; i<srcs; i++) { tempArray[i] = sourceArray[i]; } for (i=0; i<widthInt; i++) { //widthInt I'll get from someplace else, but it's an int that would tell me the second dimension of the array free(sourceArray[srcs][widthInt]); } free(sourceArray[srcs]); free(sourceArray); sourceArray = tempArray; }
     
smeger
Mac Elite
Join Date: Sep 2000
Location: Tempe, AZ
Status: Offline
Reply With Quote
Jul 29, 2005, 04:21 PM
 
You can use "realloc" to do that quite a bit more quickly.
Code:
-(void)appendSourceArray: (short** arrayToAdd) { size_t newSize = (srcs+1) * sizeof( short** ); sourceArray = (short ***)reallocf( sourceArray, newSize ); sourceArray[srcs++] = arrayToAdd; }
Geekspiff - generating spiffdiddlee software since before you began paying attention.
     
arcticmac  (op)
Dedicated MacNNer
Join Date: Apr 2004
Status: Offline
Reply With Quote
Jul 29, 2005, 04:27 PM
 
hm... I'm not all that concerned with speed at that particular location, and I'd like to get it working with calloc first (cause I think that'll be easier cause I'm starting to get to know calloc).

What about removing arrays? can I use realloc there?
     
Detrius
Professional Poster
Join Date: Apr 2001
Location: Asheville, NC
Status: Offline
Reply With Quote
Jul 29, 2005, 08:56 PM
 
Originally Posted by arcticmac
hm... I'm not all that concerned with speed at that particular location, and I'd like to get it working with calloc first (cause I think that'll be easier cause I'm starting to get to know calloc).

What about removing arrays? can I use realloc there?
I'm curious what you have against C++'s memory management, as you seem insistent on having to learn C's horrific memory management tools. All you have to do is change the extension from .m to .mm and then you can use C++. You don't have to calculate sizes with C++. You don't have to implicitly cast things. It's easier to read. C'mon dude.
ACSA 10.4/10.3, ACTC 10.3, ACHDS 10.3
     
arcticmac  (op)
Dedicated MacNNer
Join Date: Apr 2004
Status: Offline
Reply With Quote
Jul 29, 2005, 09:15 PM
 
1. you didn't tell me what I had to do to make it Objective-C++ before, so I would have had to look it up
2. I'd already started writing it with the c functions, and now I'm done writing it with the c functions, so I'd have to rework it.
3. you seem to imply that the memory returned needs to be initialized. calloc does it for me

Besides that, there's the fact that when I initially wanted to learn objective-c, my dad talked me into getting a terrible (although I didn't know it then) C++ book (called "C++ Programming Fundamentals", by Chuck Easttom...), and that's kinda got me pissed with c++... Mostly it was a waste of time... I could have learned better off your average c website, and that wouldn't have required paying.
     
proton
Senior User
Join Date: Nov 2000
Status: Offline
Reply With Quote
Jul 30, 2005, 01:47 AM
 
Originally Posted by Detrius
I'm curious what you have against C++'s memory management, as you seem insistent on having to learn C's horrific memory management tools. All you have to do is change the extension from .m to .mm and then you can use C++. You don't have to calculate sizes with C++. You don't have to implicitly cast things. It's easier to read. C'mon dude.
But you have to link in a 2MB library (and statically link it if you want to run on 10.3.8 or earlier) for something that can be done another way without too much hassle if you know C.

- proton
     
BLAZE_MkIV
Professional Poster
Join Date: Feb 2000
Location: Nashua NH, USA
Status: Offline
Reply With Quote
Jul 30, 2005, 11:56 AM
 
Make one large array and do the math to lookup the entries instead of multiple loops.

demoArrays = calloc(1, (int)sizeof(short)*x*y*z);
demoArrays[ x*ix + y*iy + iz ]
     
arcticmac  (op)
Dedicated MacNNer
Join Date: Apr 2004
Status: Offline
Reply With Quote
Jul 30, 2005, 12:06 PM
 
Originally Posted by BLAZE_MkIV
Make one large array and do the math to lookup the entries instead of multiple loops.

demoArrays = calloc(1, (int)sizeof(short)*x*y*z);
demoArrays[ x*ix + y*iy + iz ]
won't that be slower to look up though? I suppose I could try it though... run a test, and see if it's really slower.
     
BLAZE_MkIV
Professional Poster
Join Date: Feb 2000
Location: Nashua NH, USA
Status: Offline
Reply With Quote
Jul 30, 2005, 12:24 PM
 
its the same math, the subscript operator is just a convienent way of hiding the pointer math
data = *(demoArrays +( x*ix + y*iy + iz ));
would work too.
     
   
 
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Top
Privacy Policy
All times are GMT -4. The time now is 11:10 PM.
All contents of these forums © 1995-2017 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.8 © 2000-2017, Jelsoft Enterprises Ltd.,