Reputation: 71
how can I allocate memory for structure in another function than where is structure variable declared?
typedef struct{
char *IP_req;
} ARGS;
int main(int argc , char *argv[]){
ARGS *args = NULL;
mal(argc, argv, &args);
printf("arg IP:%s\n", &args->IP_req);
return 0;
}
Function where I want to allocate:
int mal(int argc , char *argv[], ARGS *args){
args=malloc(sizeof (ARGS));
args->IP_req = (char*)malloc(sizeof(char) * 200);
strcpy(args->IP_req,"12.21.51.88");
printf("arg IP:%s\n", args->IP_req);
return 0;
}
When I compile this program, I get:
arg IP:12.21.51.88
arg IP:(null)
But I expected (and want):
arg IP:12.21.51.88
arg IP:12.21.51.88
Upvotes: 1
Views: 85
Reputation: 223254
This statement in main
:
mal(argc, argv, &args);
says to pass the address of args
to mal
. The type of args
is ARGS *
, so the type of &args
is ARGS **
.
This definition of mal
:
int mal(int argc , char *argv[], ARGS *args)
says that the args
parameter has type ARGS *
. Since main
is passing an ARGS **
, not an ARGS *
, this is an error.
If you are using your compiler correctly, it should have warned you about one of the following things:
main
, no declaration of mal
is visible.main
, the call to mal
does not match its declaration.mal
does not match its declaration.If the compiler did not warn you about at least one of those, then you need to ensure two things are done:
-Wall
to the command line switches. If you are using another interface or another compiler, refer to its documentation.mal
in a header file and use #include
to include that header file in both the source file containing main
and the source file containing mal
.Putting the declaration in a header file and including that file in each source file is a better solution than copying the declaration to each source file because it ensure each source file uses the same declaration. And enabling compiler warnings—and paying attention to them—ensure there is a complete chain checking the types—the use of mal
in main
is connected to its declaration, and its declaration is connected to its definition. This enables to compiler to do all the type checking.
One way to fix the error is to make the definition of mal
match how you call it in main
. To do this, change the definition of mal
to make args
have type ARGS **
:
int mal(int argc , char *argv[], ARGS **args)
Then inside, mal
, since the type of args
has changed, you need to use *args
to refer to the ARGS *
that main
has passed to it:
*args = malloc(sizeof (ARGS));
(*args)->IP_req = malloc(sizeof(char) * 200);
strcpy((*args)->IP_req,"12.21.51.88");
printf("arg IP:%s\n", (*args)->IP_req);
return 0;
In main
, when printing a string with %s
, do not pass the address of the array, as in printf("arg IP:%s\n", &args->IP_req);
. Pass the address of the first element of the array, using printf("arg IP:%s\n", args->IP_req);
. (Although args->IP_req
initially refers to the array, it is, in this and most contexts, automatically converted to a pointer to its first element.)
In C (unlike C++), you do not need to cast the result of malloc
, so args->IP_req = (char*)malloc(sizeof(char) * 200);
can be just args->IP_req = malloc(sizeof(char) * 200);
.
When calculating sizes to pass to malloc
, it is better to use sizeof
in this way:
*args = malloc(size **args);
args->IP_req = malloc(200 * sizeof *args->IP_req);
This way, the size of the object being allocated is automatically used—if later edits to the code change the type where args
or args->IP_req
is declared, these expressions automatically use the new size. It would be necessary to change the type in two or more places (one at the declaration and one in each malloc
).
Upvotes: 1
Reputation: 51864
As pointed out in the comments by @PaulOgilvie, the last argument to mal
should be a pointer to a pointer:
int mal(int argc , char *argv[], ARGS **args) { // **args poits to the pointer to be allocated
*args = malloc(sizeof (ARGS)); // And all other 'args' herein should be dereferenced
(*args)->IP_req = (char*)malloc(sizeof(char) * 200);
strcpy((*args)->IP_req,"12.21.51.88");
printf("arg IP:%s\n", (*args)->IP_req);
return 0;
}
Your call in main: mal(argc, argv, &args);
is correct.
Upvotes: 1