Home > Net >  Why when I try to access array of structures it returns random values? (C)
Why when I try to access array of structures it returns random values? (C)

Time:01-25

I have a function that returns pointer to array of structures. However, when I try to access any of the values of returned structure, it prints random symbols.

#include <stdio.h>

struct MY {
   int i;
   char string[30];
};

struct MY* myFunc() {
  struct MY arrayOfStructs[3];
  struct MY tempStruct;
  struct MY* arrayOfStructsPtr = arrayOfStructs;

  tempStruct.i = 1;
  tempStruct.string[0] = 'H';
  tempStruct.string[1] = 'i';
  arrayOfStructs[0] = tempStruct;

  tempStruct.i = 2;
  tempStruct.string[0] = 'L';
  tempStruct.string[1] = 'o';
  arrayOfStructs[1] = tempStruct;

  tempStruct.i = 3;
  tempStruct.string[0] = 'M';
  tempStruct.string[1] = 'Y';
  arrayOfStructs[2] = tempStruct;

  return arrayOfStructsPtr;
}

int main()
{
   struct MY* arrayOfStructs = myFunc();
   for(int i = 0; i < 3; i  ) printf("%d\n", arrayOfStructs[i].i);
   return 0;
}

CodePudding user response:

You return a reference to the local array which stops to exist when function returns. It is Undefined Behaviour.

You need:

struct MY* myFunc(void) {
  static struct MY arrayOfStructs[3];

or

struct MY* myFunc(void) {
  struct MY *arrayOfStructs = malloc(3 * sizeof(*arrayOfStructs));

or pass the buffer allocated by the caller.

struct MY *myFunc(struct MY *arrayOfStructs) {
   /* .... */

If you dynamically allocate memory you should free it after use

CodePudding user response:

You return a pointer to a local variable which is out of scope when the function returns. Some alternatives:

  1. The caller main() allocates variable and pass it to myFunc() for initialization.
#include <stdio.h>
#include <string.h>

#define N 3

struct MY {
    int i;
    char string[30];
};

void myFunc(struct MY arrayOfStructs[N]) {
    char *strings[N] = { "Hi", "Lo", "MY" };
    for(size_t i = 0; i < N; i  ) {
        arrayOfStructs[i].i = i   1;
        strcpy(arrayOfStructs[i].string, strings[i]);
    }
}

int main() {
    struct MY arrayOfStructs[N];
    myFunc(arrayOfStructs);
    for(int i = 0; i < N; i  )
        printf("%d\n", arrayOfStructs[i].i);
}

As used here you don't really need to store i as it's just index of the struct 1.

  1. myFunc() dynamically allocate the variables with malloc() and return the pointer. Caller is responsible for free'ing the allocated memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 3

struct MY {
    int i;
    char string[30];
};

struct MY *myFunc() {
    struct MY *arrayOfStructs = malloc(N * sizeof *arrayOfStructs);
    if(!arrayOfStructs) return NULL; // malloc failed
    char *strings[N] = { "Hi", "Lo", "MY" };
    for(size_t i = 0; i < sizeof strings / sizeof *strings; i  ) {
        arrayOfStructs[i].i = i   1;
        strcpy(arrayOfStructs[i].string, strings[i]);
    }
    return arrayOfStructs;
}

int main() {
    struct MY *arrayOfStructs = myFunc();
    if(!arrayOfStructs) return 1;
    for(int i = 0; i < N; i  )
        printf("%d\n", arrayOfStructs[i].i);
    free(arrayOfStructs);
}
  1. myFunc(): make variables static (not recommended).
  • Related