In addition to the other corrections, if you will need ppa
back in the calling function main
, you have no way of returning a value to main
. While there is exercise value in what you are doing, your actual goal is anything but clear. It is somewhat of an XY problem, see: What is the XY problem?.
That said, reading between the lines, and to make ppa
available back in main
, your parseB
would have to somehow return a value. You could do so by changing the type
to A *parseB (B **ppb)
.
Further, you seem to have a bit of confusion in whether to declare ppa
and ppb
as pointers or pointer-to-pointer-to-type. Given your initialization and use, it appears you want a pointer to both ppa
and ppb
. You would then pass the address of each to the functions parseB
and parseA
and dereference accordingly to allocate storage for their contents. Doing so, you could craft a parseB
similar to:
A *parseB (B **ppb)
{
A *ppa = NULL;
void *tmp = realloc (*ppb, sizeof **ppb);
if (!tmp) {
fprintf (stderr, "error: realloc ppb.\n");
return NULL;
}
*ppb = tmp;
parseA (&ppa);
if (ppa)
**ppb = makeB (*ppa);
return ppa;
}
note: realloc
is used for the allocation, because you have no control over whether *ppb
has been previously allocated within parseB itself (you do have control over what you send to parseA
from parseB
so malloc
is fine in parseA
)
To start this daisy-chain of allocation and assignment of values, your main
could be written similar to:
int main ()
{
B *ppb = NULL;
A *ppa = parseB (&ppb);
if (ppa && ppb) {
printf ("ppa->x: %d\nppa->y: %d\n\n"
"ppb->a.x: %d\nppb->a.y: %d\nppb->z: %d\n",
ppa->x, ppa->y, ppb->a.x, ppb->a.y, ppb->z);
free (ppa);
free (ppb);
}
return 0;
}
Granted, I do not have a clear picture of what you are ultimately attempting to accomplish. So to make use of the values you assign, the pointer level of indirection at the declaration was reduced to make sense of what it looked like you were trying to do. That said, and putting all the pieces together, you could do something similar to the following:
#include <stdio.h>
#include <malloc.h>
typedef struct {
int x;
int y;
} A;
typedef struct {
A a;
int z;
} B;
A makeA ()
{
return (A) {.x = 1,.y = 2};
}
B makeB (A a1)
{
return (B) {.a = a1,.z = 3};
}
void parseA (A **ppa)
{
*ppa = malloc (sizeof (A));
**ppa = makeA ();
}
A *parseB (B **ppb)
{
A *ppa = NULL;
void *tmp = realloc (*ppb, sizeof **ppb);
if (!tmp) {
fprintf (stderr, "error: realloc ppb.\n");
return NULL;
}
*ppb = tmp;
parseA (&ppa);
if (ppa)
**ppb = makeB (*ppa);
return ppa;
}
int main ()
{
B *ppb = NULL;
A *ppa = parseB (&ppb);
if (ppa && ppb) {
printf ("ppa->x: %d\nppa->y: %d\n\n"
"ppb->a.x: %d\nppb->a.y: %d\nppb->z: %d\n",
ppa->x, ppa->y, ppb->a.x, ppb->a.y, ppb->z);
free (ppa); /* if you allocate it, it is up to you to free it */
free (ppb);
}
return 0;
}
Example Use/Output
$ ./bin/structptrissue
ppa->x: 1
ppa->y: 2
ppb->a.x: 1
ppb->a.y: 2
ppb->z: 3
Memory Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to write beyond/outside the bounds of your allocated block of memory, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind
is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/structptrissue
==19399== Memcheck, a memory error detector
==19399== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==19399== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==19399== Command: ./bin/structptrissue
==19399==
ppa->x: 1
ppa->y: 2
ppb->a.x: 1
ppb->a.y: 2
ppb->z: 3
==19399==
==19399== HEAP SUMMARY:
==19399== in use at exit: 0 bytes in 0 blocks
==19399== total heap usage: 2 allocs, 2 frees, 20 bytes allocated
==19399==
==19399== All heap blocks were freed -- no leaks are possible
==19399==
==19399== For counts of detected and suppressed errors, rerun with: -v
==19399== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.