You don't need a "double pointer"; you need a pointer to the object you want to modify. If you want the function to modify a pointer object, you need to pass a pointer to that object. If you want the function to modify a structure, you need to pass a pointer to that object.
And that's exactly what your code does. You want to modify main's tray, so you pass a pointer to main's tray. So your code works.
The following demonstrates this.
First, let's look at the code that doesn't work.
void fac( int *ac ) {
ac = malloc( sizeof( int ) );
}
int main( void ) {
int *a = NULL;
fac( a );
printf( "%p\n", (void *)a ); // XXX `a` isn't modified.
}
This code modifies ac, but it does not modify a. It does not achieve what we want it to achieve. To modify a, we would need to pass the address of a.
void fap( int **ap ) {
*ap = malloc( sizeof( int ) );
}
int main( void ) {
int *a = NULL;
fap( &a );
printf( "%p\n", (void *)a ); // XXX `s` isn't modified.
}
Here, rather than modifying the parameter, we modify *ap which is a. This code does achieve what we want it to achieve.
Now, let's introduce structs.
typedef struct { int *a } S;
void fsc( S sc ) {
sc.a = malloc( sizeof( int ) );
}
int main( void ) {
S s = { .a = NULL };
fsc( s );
printf( "%p\n", (void *)(s.a) ); // Ok. `s` is modified.
}
This code modifies sc, but it does not modify s. It does not achieve what we want it to achieve. To modify s, we would need to pass the address of s.
typedef struct { int *a } S;
void fsp( S *sp ) {
sp->a = malloc( sizeof( int ) ); // `sp->a` means `(*sp).a`
}
int main( void ) {
S s = { .a = NULL };
fsp( &s );
printf( "%p\n", (void *)(s.a) ); // Ok. `s` is modified.
}
Here, rather than modifying the parameter, we modify *sp which is s. This code does achieve what we want it to achieve.
Full demo:
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct { int *a; } S;
void fac( int *ac ) {
ac = malloc( sizeof( int ) );
}
void fap( int **ap ) {
*ap = malloc( sizeof( int ) );
}
void fsc( S sc ) {
sc.a = malloc( sizeof( int ) );
}
void fsp( S *sp ) {
sp->a = malloc( sizeof( int ) ); // `sp->a` means `(*sp).a`
}
int main( void ) {
int *a = NULL;
fac( a );
printf( "%p\n", (void *)a ); // XXX `a` isn't modified.
fap( &a );
printf( "%p\n", (void *)a ); // Ok. `a` is modified.
S s = { .a = NULL };
fsc( s );
printf( "%p\n", (void *)(s.a) ); // XXX `a` isn't modified.
fsp( &s );
printf( "%p\n", (void *)(s.a) ); // Ok. `s` is modified.
}
Warnings:
<source>: In function 'fac':
<source>:10:16: warning: parameter 'ac' set but not used [-Wunused-but-set-parameter]
10 | void fac( int *ac ) {
| ~~~~~^~
<source>: In function 'fsc':
<source>:18:13: warning: parameter 'sc' set but not used [-Wunused-but-set-parameter]
18 | void fsc( S sc ) {
| ~~^~
Output:
(nil)
0x158a2d0
(nil)
0x158a310
allocateTray(n, &tray); for (int i = 0; i<n; i++) { printf("tray.parr[%d] = %d \n", i, tray.parr[i]); }. You don't needptrayin this case.struct Tray *tray, then the initializer would beNULLdouble *dp; int **ipp. Here,dpis a "double pointer", butippis not a "double pointer".