4

Below is the sample code for populating the array of struct R using double pointers. I am unable to allocate memory to r[0] and also when the function exits, both r and r[0] becomes 0x0.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct R
{
  int x;
  int y;
  char * z;
};

void func(struct R **r)
{
  r = (struct R **) malloc(4 * sizeof(struct R *));
  r[0] = (struct R *) malloc(sizeof(struct R));   // giving r[0] = 0x0
  r[0]->x = 1;
  r[0]->y = 2;
  r[0]->z = (char *) malloc(64 * sizeof(char));
  strcpy(r[0]->z , "HELLO");
}

int main()
{
  struct R *r = NULL;
  func(&r);
  printf("%d", r->x);
  printf("%d", r->y);
  printf("%s", r->z);
  return 0;
}

I am unable to find the reason behind it. Any help would be highly appreciated.

Azeem
  • 11,148
  • 4
  • 27
  • 40
Bhawan
  • 2,441
  • 3
  • 22
  • 47

3 Answers3

7

The line

r = (struct R **) malloc(4 * sizeof(struct R *));

changes where r points but only locally in the function. It does not change the value of the pointer in the calling function.

What you need is:

void func(struct R **r)
{
   *r = malloc(sizeof(struct R));

   r[0]->x = 1;
   r[0]->y = 2;
   r[0]->z = malloc(64 * sizeof(char));
   strcpy(r[0]->z , "HELLO");
}

Another option is to change the return value of func to a pointer and make it simpler to use.

struct R * func()
{
   struct R *r = malloc(sizeof(*r));

   r->x = 1;
   r->y = 2;
   r->z = malloc(64 * sizeof(char));
   strcpy(r->z , "HELLO");

   return r;
}

and use it in main as:

struct R *r = func();

PS See Do I cast the result of malloc? to understand why you should not cast the return value of malloc.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • An even better recommendation (than the usual "don't cast malloc") would be to use the `sizeof` operator on the actual *variable*, instead of repeating the type again. I.e. `int *x = malloc(sizeof *x)` always works and is a simple rule to remember, while the main problem with casting malloc (implicit `int` function declaration) is no longer an issue as of C11, and not even with earlier compilers with proper warnings enabled. – vgru Mar 30 '18 at 09:02
4

You want an array of struct R, then why are you reserving space for an array of pointers to struct R?

Change to:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct R
{
  int x;
  int y;
  char * z;
};

void func(struct R **r)
{
  /* Dereference in order to change the value of r */
  *r = malloc(4 * sizeof(struct R)); /* Don't cast malloc */
  r[0]->x = 1;
  r[0]->y = 2;
  r[0]->z = malloc(64); /* char is always 1 byte */
  strcpy(r[0]->z , "HELLO");
}

int main(void) /* Correct prototype */
{
  struct R *r = NULL;

  func(&r);
  printf("%d", r[0].x);
  printf("%d", r[0].y);
  printf("%s", r[0].z);
  /* Don't forget to free */
  free(r[0].z);
  free(r);

  return 0;
}
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
1

This line:

void func(struct R **r)
{
  r = (struct R **) malloc(4 * sizeof(struct R *));

No matter what type r is, it's still a local variable. If you assign a local variable, the caller part won't be affected. This code is similar to

void func(int r)
{
  r = 1;
}
llllllllll
  • 16,169
  • 4
  • 31
  • 54