0

I am trying to create a structure on the heap - so that it can be used in other functions, but I can't seem to get past the first hurdle of creating the structure itself in a way that I can pass it along with a pointer. I know that the field arrays are properly initialized 5 by 5, and I can get the pointer (*f) to the fieldz struct, but when I try to pass it back to main, nothing comes along. I need to keep field_t * f = makeField(w,h); as is, I feel like I am missing something obvious.

Thanks!

struct _field_t {
  int ** field;
  int width;
  int height;
};
typedef struct _field_t field_t;

field_t * makeField(int w, int h){
  field_t fieldz;
  fieldz.width = w;
  fieldz.height = h;
  int ** fieldz = malloc(h * sizeof(* fieldz));
  for(int y = 0; y < h; y++){
    int * row = malloc(w * sizeof(* row));
    fieldz[y] = row;
    for(int x = 0; x < w; x++){
      row[x] = -1;
    }
  }
  fieldz.field = field;
  field_t * f = &fieldz;
  return f;
}
int main() {
  int h = 5;
  int w = 5;
  field_t * f = makeField(w, h);
  return 0;
}
Ali Z
  • 47
  • 6
  • 1
    This is a duplicate (have to search to what) - you are returning a pointer to a local object which doesn't exist at the completion of the call to makeField. – John3136 Oct 26 '18 at 00:09
  • 1
    @John3136 https://stackoverflow.com/q/17997228/251311 perhaps? (C++ not C but still) or https://stackoverflow.com/q/5289015/251311 – zerkms Oct 26 '18 at 00:09
  • 1
    Possible duplicate of [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) I know this is C++ but it gives a good explanation. – John3136 Oct 26 '18 at 00:10
  • 1
    This code won't even compile. I don't see `field` declared anywhere? Also `field_t fieldz;` is followed by `int ** fieldz`. Is that intentional? – Sandy Oct 26 '18 at 00:19
  • 2
    And purely a matter of form, but at least attach your pointer asterisk to either the type or the name (won't start the holy war of which to chose, but we all know only one of them is right) – visibleman Oct 26 '18 at 00:25
  • You never actually explained how your program was failing (was it a compilation error, a runtime error, a segmentation fault, something else?) other than the vague and slightly mysterious "nothing comes along". Please try to provide specific details in future questions. – jarmod Oct 26 '18 at 00:35
  • @jarmod it actually compiles fine, the issue arises when I try to utilize the pointer that I tried to return in subsequent actions. – Ali Z Oct 26 '18 at 00:52
  • It doesn't compile. You have two automatic variables named fieldz in the same scope. But that's not the point. The point is that you did not provide any specific details of what was going wrong. – jarmod Oct 26 '18 at 01:03
  • @john3136 didn't EXACTLY answer, but 1) it was a great reference! 2) led me down the rabbit hole towards what I really needed to do in order to access the pointer outside of the local function by sparking an understanding in the posts subsequent writing. so thank you! – Ali Z Oct 26 '18 at 17:34
  • @visibleman which one is right?! Asking for a friend (LOL, I'm a noob with C). – Ali Z Oct 26 '18 at 17:37
  • @AliBaba, First, if you are working with others, then just follow project standard. Since it is all about readability/consistency. To me, putting the asterisk in the middle scans a little bit like multiplication to the human eye. I prefer to attach the asterisk to the type, as I feel that the 'int* offset' then tells me this is a pointer to an int named offset. To me, attaching to the name scans a little bit like a deference. Also, function declarations don't need named arguments, so it is easier to be consistent by attaching to type. SO programmers seem to be about 50/50 divided on the issue – visibleman Oct 29 '18 at 00:30

1 Answers1

0

(This answer is going to ignore the typo int **fieldz)

Returning a pointer to a local variable is a big No-No. I am not going to elaborate since this has been explained many times already (Google, bing and duck-duck-go are your friends)

There are basically three ways to have functions create structs

1 - Malloc the struct and return the pointer to it:

field_t * makeField(int w, int h)
{
   field_t *f = malloc(sizeof (*f))
   f->width = w;
   f->height = h;
   f->field = .....;

   return f;
}
.....
field_t *f = makeField(50, 50);

2 - Let the caller allocate memory and pass a pointer to the struct to be initialized

field_t * makeField(field_t *f, int w, int h)
{
   f->width = w;
   f->height = h;
   f->field = .....;

   return f;
}
.....
field_t f1;
makeField(&f1, 50, 50);

field_t *f2 = malloc(sizeof(*f2));
makeField(f2, 50, 50);

3 - Let the caller allocate memory and assign a copy of the struct created by makeField

field_t makeField(int w, int h)
{
   field_t f;
   f.width = w;
   f.height = h;
   f.field = .....;

   return f;
}
.....
field_t f1 = makeField(50, 50);

field_t *f2 = malloc(sizeof(*f2));
*f2 = makeField(50, 50);

Which ever method you use is determined by needs and personal preferences. Personally I prefer to let the caller allocate memory when possible. The caller normally knows better if stack, heap or something else is more appropriate

HAL9000
  • 2,138
  • 1
  • 9
  • 20