C question: Nested sturctures and arrays with Xcode?

Apprentice
Posts: 12
Joined: 2008.01
Post: #1
I got this code from the book "Black Art of 3D Game Programming", and changed them to suit my Xcode program:

Code:
typedef struct sprite_typ    
{
    int x,y;        //position of the sprite
    int width,height;        //dimensions of the sprite
    int sourcex, sourcey;    

    //and so on and so forth, the rest isn't important
    
} sprite, *sprite_ptr;


void GameApp::Sprite_Init(sprite_ptr sprite,int x,int y, int sourcex, int sourcey,    int width, int height //etc...)
{
    sprite->x            = x;
    sprite->y            = y;
    sprite->sourcex        = sourcex;
    sprite->sourcey        = sourcey;
    sprite->width        = width;
    sprite->height        = height;

    //again, so on and so forth...    
}




I then tried to add my own structure in a similar manner, using the previous structure as a nested stucture:


Code:
typedef struct piece_typ
{
    int source_array[2][3];
    sprite block;

    //yada yada yada...    

} t_piece, *t_piece_ptr;
    

void GameApp::Piece_Init(t_piece_ptr piece, int *source_array, sprite_ptr block)
{
    piece->source_array[1][2] =         source_array[1][2];     //this line errs
    piece->block    =    block;     //so does this
}


There are no errors until the last function where I try to initialize the structure. It seems that no amount of asterisks, ampersands, and (sprite_ptr) prefixes work. If I can get these two statements to work, I can make an array copying function and everything else later. But I'm stumped. Maybe it has something to do with the fact that I'm copying functions written for a Microsoft C DOS program and using them in an Xcode C++ program? I've been avoiding C++ as much as possible.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #2
This problem looks like it has nothing to do with your structs. It's the way you're handling the parameters passed into your function.

On the first error line, you're trying to access source_array[1][2]. However, source_array's type is int *, which can't be used as a two-dimensional array because the stride between the first and second dimension is undefined. You'll have to either pass it to your function as a two-dimensional array, or index it as a one-dimensional array.

On the next line, you're trying to assign a value of type sprite_ptr to a field of type sprite. You'll have to dereference block if you want to copy its contents into the struct field.

For future reference, it helps with troubleshooting if you paste the exact text of compiler error messages you're getting for the relevant lines. This wasn't too hard to spot, but it would have been much quicker if the full text of the compile errors was available.
Quote this message in a reply
Member
Posts: 59
Joined: 2007.12
Post: #3
For copying arrays, you need to use "for" loops or memcpy for larger arrays.
Quote this message in a reply
Apprentice
Posts: 12
Joined: 2008.01
Post: #4
Thanks for the responses. Here's the original errors:

Code:
GameApp.cp:389: error: invalid types 'int[int]' for array subscript

GameApp.cp:390: error: no match for 'operator=' in 'piece->GameApp::piece_typ::block = block'

Quote:You'll have to either pass it to your function as a two-dimensional array, or index it as a one-dimensional array.

I don't know how to do the former, is it simple? And for the latter, that simply takes x times the width of the array plus y to get the desired index, right?

Quote:You'll have to dereference block if you want to copy its contents into the struct field.

So by dereference I assume you mean something like this:

Code:
piece->block.x     = block.x;

Having tried that, I get this error:

Code:
GameApp.cp:390: error: request for member 'x' in 'block', which is of non-class type 'GameApp::sprite_typ*'

Now don't tell me I need to dereference each data member in the function prototype!? Or does this "class" lingo have something to do with my hybrid C/C++ code?

Quote:For copying arrays, you need to use "for" loops or memcpy for larger arrays.

Yah, I know, I just wanted to get something simple working first. I'll probably have to use memcpy even though the arrays are small because different-sized arrays will be sent to the same function (correct? I'm new to this!).
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #5
zmwworm Wrote:I don't know how to do the former, is it simple?

Sure. Instead of declaring GameApp::Piece_Init's second parameter as int *source_array, you'd declare it as int source_array[2][3] (or whatever source_array's dimensions are supposed to be). As long as you're only passing arrays of exactly that size to the function, it'll work.

zmwworm Wrote:And for the latter, that simply takes x times the width of the array plus y to get the desired index, right?

Close. (y * width) + x, not (x * width) + y.

zmwworm Wrote:So by dereference I assume you mean something like this:

Code:
piece->block.x     = block.x;

Not quite. Remember, block is of type sprite_ptr, not sprite, so block.x is invalid. block->x or (*block).x are both valid. You can also do piece->block = *block to copy the whole thing. If this doesn't make intuitive sense to you, it might be a good idea to study how pointers work in C.

Hope this helps!
Quote this message in a reply
Apprentice
Posts: 12
Joined: 2008.01
Post: #6
ThemsAllTook Wrote:You can also do piece->block = *block to copy the whole thing. If this doesn't make intuitive sense to you, it might be a good idea to study how pointers work in C.

Hope this helps!

Thanks a ton, I'll try that. I didn't know you could use pointers with structures like that. And yes it would be an excellent idea for me to study pointers, this project is becoming my pointers-and-structures lesson.
Quote this message in a reply
Member
Posts: 59
Joined: 2007.12
Post: #7
zmwworm Wrote:Yah, I know, I just wanted to get something simple working first. I'll probably have to use memcpy even though the arrays are small because different-sized arrays will be sent to the same function (correct? I'm new to this!).

Not really, you simply do

for(int i=0; i<array_size; ++i) {

copy stuff;

}

Same goes for multidimensional arrays. You can use nested loops there. Memcpy isn't really worth it unless: 1. You're too lazy to write for loops Rasp 2. The array's reaaally big.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #8
_ibd_ Wrote:Not really, you simply do

for(int i=0; i<array_size; ++i) {

copy stuff;

}

Same goes for multidimensional arrays. You can use nested loops there. Memcpy isn't really worth it unless: 1. You're too lazy to write for loops Rasp 2. The array's reaaally big.

In my tests on a 2.4 GHz Core 2 Duo MacBook Pro, compiling with -O3, memcpy is faster for every case except copying a single value. The savings grow as your size gets bigger. So, I'd define "reaaally big" as only a few bytes. Smile
Quote this message in a reply
Member
Posts: 59
Joined: 2007.12
Post: #9
Cool, I didn't know that. Thanks!
Quote this message in a reply
Apprentice
Posts: 12
Joined: 2008.01
Post: #10
_ibd_ Wrote:Not really, you simply do

for(int i=0; i<array_size; ++i) {

copy stuff;

}

Same goes for multidimensional arrays. You can use nested loops there. Memcpy isn't really worth it unless: 1. You're too lazy to write for loops Rasp 2. The array's reaaally big.

I got everything working using nested loops, but for future reference, can I get a sample of memcpy() used properly, and can it be used to copy arrays of variable size? Also, how would I prototype a function to accept an array of variable size?
Quote this message in a reply
Member
Posts: 59
Joined: 2007.12
Post: #11
Yes, memcpy works for any size of array. For functions that accept variable sized arrays, you'd usually pass the size to the function (void doStuff(int * data, int size)Wink.
Quote this message in a reply
Apprentice
Posts: 12
Joined: 2008.01
Post: #12
I've got a new problem. This line worked fine as long as both piece and block were sent as parameters to the function:

piece->block = *block;

But how can I do the copy if I want to copy a pre-made sprite structure, rather than a parameter in the function? For instance, I want to do the following in a different part of the program, after I've already defined and initialized the sprite RLLBlock:

thePiece->block = *RLLBlock;

This line errs, something about there not being a match for 'operator*' in '*RLLBlock'. I understand that it should be different because I'm using an actual structure rather than a pointer to it or whatever. But I don't know how it should be done. Any help?
Quote this message in a reply
Member
Posts: 254
Joined: 2005.10
Post: #13
thePiece->block = *RLLBlock would be translated as "assign the value pointed to by RLLBlock to the block member of thePiece". My guess is that RLLBlock is not a sprite_ptr but a sprite, so putting the star on there has no meaning.
Quote this message in a reply
Apprentice
Posts: 12
Joined: 2008.01
Post: #14
Blacktiger Wrote:thePiece->block = *RLLBlock would be translated as "assign the value pointed to by RLLBlock to the block member of thePiece". My guess is that RLLBlock is not a sprite_ptr but a sprite, so putting the star on there has no meaning.

So maybe I need to declare a pointer to RLLBlock and use that instead?
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #15
zmwworm Wrote:So maybe I need to declare a pointer to RLLBlock and use that instead?

Or just omit the *...
Quote this message in a reply
Post Reply