Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Passing struct array by reference

This thread is locked; no one can reply to it. rss feed Print
Passing struct array by reference
AceBlkwell
Member #13,038
July 2011
avatar

All,

I'm working on a program. My goal in the coding is to pass various structs to initialization functions. To do this I want to pass them by reference. So far I can't figure out how to pass an array of structures by reference. I've searched the web and have tried trial & error. No luck. In the example below I get... invalid initialization of reference of type 'Cards&' from expression of type 'Cards [8]' match_config(sCards);

#SelectExpand
1#include <cstdio> 2#include <cstdlib> 3#include <iostream> 4 5/********************* DEFINES ******/ 6#define LIMIT 8 7 8 9/********************* STRUCTS ******/ 10struct Cards { 11 12 bool bMatched; 13 bool bFlipped; 14 char cValue; 15 int iX; 16 int iY; 17 int iBdPosition; 18}; 19 20/********************* FUNCTION DECLARE ******/ 21int random_no(int); 22void match_config(Cards & sCards); 23 24 25 26int main(int argc, char *argv[]){ 27 28 Cards sCards[LIMIT]; 29 match_config(sCards); 30 return 0; 31 32} //end main() 33 34void match_config (Cards & sCards){ 35 36 int setup[LIMIT]; 37 int hold = 0; 38 int check = 0; 39 char card = 'A'; 40 int matches = 0; 41 int fchoice = 0; 42 int schoice = 0; 43 44 for(int count = 0;count<8;count++){ 45 hold = random_no(8); 46 for(int a_count=0;a_count<8;a_count++){ 47 if(hold == setup[a_count]){ 48 check = 1; 49 count--;}//end if 50 }//inner for 51 if(check == 0) 52 setup[count]=hold; 53 check = 0; 54 55 }// end outer for 56 57 for(int count = 0;count<8;count++){ 58 if(count !=0 && count % 2 == 0) 59 card++; 60 sCards[1].cValue = card; 61 sCards[1].bMatched ='N'; 62 }//for outer 63 64 std::cout<<"Match Board "<<std::endl; 65 for(int count = 0;count<4;count++) 66 std::cout<<count+1<<" ";//end for 0-3 67 std::cout<<std::endl; 68 for(int count = 4;count<8;count++) 69 std::cout<<count+1<<" ";//end for 4-7 70 std::cout<<std::endl; 71 72 73} //end of match_config()

DanielH
Member #934
January 2001
avatar

Arrays are funny that way.

In your code, you are passing one Cards, not an array of Cards.

// one Cards
void match_config(Card & sCards) {}

I would just pass sCards as a pointer. sCards is already a pointer. You might have declared it as an array, but it's a pointer.

// pointer to array
void match_config(Cards* sCards) {}
//or supply a length if your length is not defined elsewhere like it is with LIMIT
void match_config(Cards* sCards, size_t len) {}

If you REALLY want to pass by reference,

void match_config(Cards (&sCards)[]) {}
// or
void match_config(Cards (&sCards)[LIMIT]) {}

As before, if LIMIT is not defined globally then you could do something like this

void match_config(Cards (&sCards)[], size_t len) {}

torhu
Member #2,727
September 2002
avatar

Since you're using C++, it would make sense to use std::vector or the new std::array and pass that by reference instead of dealing with plain arrays and pointers.

https://en.cppreference.com/w/cpp/container/array

DanielH
Member #934
January 2001
avatar

That too.

std::vector<VARTYPE> vector;
std::array<VARTYPE,ARRAYSIZE> array;

They are nearly identical. One difference is with an array, the size is specified in the beginning. It cannot be resized.

Vectors can be resized and will as you modify it.

Other difference is the internal memory:

The address of an array's memory does not change once it is created. However, every time a vector is resized, it has to allocate memory in another location and then copy all the data from the first location to the second.

Dizzy Egg
Member #10,824
March 2009
avatar

OOP anyone!? Could get this all done with a class??

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

AceBlkwell
Member #13,038
July 2011
avatar

Thanks All,

You know with so many ways to accomplish this, you would think I would have stumbled across one of them on my own. Thanks Again.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Prefer pointers to references. When using a reference it isn't always clear that the object isn't local. Also, don't return a reference or pointer to a stack object. That would go out of scope and leave you with a dangling pointer.

When using a pointer, you have to specify that it is an address - &data and it is clear that it can be modified.

If you have to, use a const& , a constant reference. This is safe, and the compiler will catch many errors this way.

Kitty Cat
Member #2,815
October 2002
avatar

Presuming you're using a modern version of C++, you can also use a span (C++20).

void match_config(std::span<Cards> sCards);
// Or if you want a fixed/compile-time size:
void match_config(std::span<Cards,LIMIT> sCards);

(note it's not passed by reference or pointer; it is the pointer).

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

AceBlkwell
Member #13,038
July 2011
avatar

Thanks All.

I agree reference is more confusing as it looks like a local variable. I'll have to consider that.

I've never heard of span but will look into it.

DanielH
Member #934
January 2001
avatar

For simple structs (containing only primitive variables) pass as value. If it is complex or you need to reference the struct (treat as a pointer) then pass as reference.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

DanielH said:

If it is complex or you need to reference the struct (treat as a pointer) then pass as reference.

No, you should really pass it as a pointer, for the reasons I mentioned above.

The asterisk reminds you it's special and you can modify the object. Otherwise you might forget you're working with a reference.

DanielH
Member #934
January 2001
avatar

Don't forget. That's on you.

Pass by reference! :D

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

DanielH
Member #934
January 2001
avatar

Yes, that's why pass by reference.

I prefer to keep the variable the same form. If it's a pointer, pass by pointer. If not, pass by reference.

I'm just messing you. Do what you want and let's agree to disagree.

Polybios
Member #12,293
October 2010

Prefer pointers to references. When using a reference it isn't always clear that the object isn't local.

No. - Do pass by reference! If it is not some POD that be better passed as value anyways. References cannot be nullptr / NULL and you can't do nasty stuff with them as with pointers.

If there are problems tracking what is a local variable and what is an argument, it's quite likely that your functions / methods are just too long.

Only use pointers when you have to.

Prefer const references to non-const references. If transferring ownership, then move (Type &&someStuff / std::move) happily.

Go to: