0

I am having trouble getting a nested array of structs to retain its members after returning from a function call.

Here is what I have defined in the header files (condensed struct members for readability):

typedef struct {
    char *name;
} weapon;

#define MAX_SHOP_ITEMS 10
struct shop {
    weapon items[MAX_SHOP_ITEMS];
};

typedef struct {
    char *name;
    struct shop shop;
} location;

I use these functions to add members to the shop.items[] array of structs. The beginnerWeapon[] is type weapon and has elements 0 and 1 declared in another file:

void PopulateShop(location loc)
{
    printf("DEBUG: character location pointer: %s\n\n\n", loc.name);

    loc.shop.items[0] = beginnerWeapons[0];
    loc.shop.items[1] = beginnerWeapons[1];

    printf("DEBUG: loc.shop.items[0].name: %s\n\n\n", loc.shop.items[0].name);
}

void ShowItems(location loc)   
{
    printf("DEBUG: location pointer in ShowItems(): %s\n\n\n", loc.name);
    printf("DEBUG: loc.shop.items[0].name: %s\n\n\n", loc.shop.items[0].name);
}

Now, when I pass a location to each function from another file through this function:...

void ShopMenu(location loc)
{
    PopulateShop(loc);
    ShowItems(loc);
}

...the debugs show the location name correctly in both functions, the correct weapon name shows up in PopulateShop(), but the shop.items[] array changes don't stick by the time I call ShowItems(). I'm not sure if I need to allocate memory for .items[], or externalize it, or pass pointers instead (which I'm not entirely sure how to do with subscripting), or perhaps I'm defining shop incorrectly. Any help is appreciated!

Jahni Slim
  • 21
  • 6
  • 6
    Common problem. Function parameters in C are pass by value. Changes inside a function to a function parameter have no effect on the caller's values. Pass in a pointer if you want to change the original struct. – kaylum Jul 02 '17 at 02:35
  • Possible duplicate of [Passing struct to function](https://stackoverflow.com/questions/10370047/passing-struct-to-function) – kaylum Jul 02 '17 at 02:39
  • A problem may also be in how `name` is assigned and copied. – chux - Reinstate Monica Jul 02 '17 at 13:55

1 Answers1

0

Fixed by using pointers as suggested by Kaylum --

void PopulateShop(location *locIn)
{
    location loc = *locIn;

    loc.shop.items[0] = beginnerWeapons[0];
    loc.shop.items[1] = beginnerWeapons[1];

    *locIn = loc;
}

Took me a minute to realize I needed to save the local variable back into the pointer. Thanks for the help!

Edit:

BE CAREFUL -- this only works for structs due to the copy constructor for structures doing a copy of members... David C. Rankin

Good to know.

locIn->shop.items[0] = beginnerWeapons[0];
locIn->shop.items[1] = beginnerWeapons[1];

which I also learned is equivalent to

(*locIn).shop.items[0] = myArr[i];

As I mentioned at the top, I wasn't sure how to use pointers with struct subscripting. Now I have another feather in my learning cap, thanks folks!

Jahni Slim
  • 21
  • 6
  • BE CAREFUL -- this only works for structs due to the *copy constructor* for structures doing a copy of members. If `loc` was any other locally declared compound type, e.g. an array, you would be assigning the address of values local to `PopulateShop` to `*locIn` which would be destroyed on function return when the function stack memory is released for reuse. – David C. Rankin Jul 02 '17 at 04:29
  • 3
    Or just drop `loc` and use `locIn->` instead of `loc.`. – alk Jul 02 '17 at 08:06