Continuing from the comments, your initial problem is you are passing a pointer by-value to your function abc()
. The function will receive a copy of the pointer and any changes you make to the copy of the pointer in function abc()
will be lost when the function returns. (you also incorrectly dereference *t->c = "hello";
)
You have two optons:
Pass the Address Of the Pointer
When you pass the address of the pointer to your function, you will pass a pointer-to-pointer holding the original address of your pointer from main()
to your function. You can then change the address held by the original pointer by updating the address held by the original pointer in your abc()
function. For example:
#include <stdio.h>
#include <stdlib.h>
struct abc {
char *c;
};
void abc (struct abc **t) /* use pointer-to-poitner to struct abc */
{
*t = malloc (sizeof **t); /* allocate */
if (*t == NULL) { /* validate */
perror ("malloc-*t");
return;
}
(*t)->c = "hello"; /* assign on success */
}
int main (void) { /* void main only valid in freestanding environment */
struct abc *k;
abc (&k); /* call abc passing address of k */
if (k) { /* validate k not NULL */
puts (k->c);
free (k); /* don't forget to free what you allocate */
}
}
(note: you must validate EVERY allocation by checking the return from malloc()
is not NULL
)
Also note the use of the derefernced pointer to set the type-size for the allocation. If you always use the dereferenced pointer to set the type-size, you will never get it wrong. In C, there is no need to cast the return of malloc
, it is unnecessary. See: Do I cast the result of malloc?.
The parenthesis around (*t)->c = "hello";
are necessary for C-operator precedence. If you omit them (e.g. *t->c
), you will receive an error because t
(holding the address of the original pointer) is not type struct abc*
, but instead is type struct abc**
and as such has no member named c
.
Exmaple Use/Output
$ ./bin/abc_ptr2ptr
hello
Change The Function Return Type to struct abc *
And Return Allocated Pointer
Your second option is simply to change the return type of your abc()
function to return a pointer to struct abc
(e.g. struct abc*
). Making that change you do not need to pass any parameter to your function. You can simply declare the pointer local to your function and allocate storage for one struct abc
assigning the address of the allocated block to your local pointer and then return that pointer to the caller (main()
here)
For example, you could do:
#include <stdio.h>
#include <stdlib.h>
struct abc {
char *c;
};
struct abc *abc (void) /* return pointer to allocated struct */
{
struct abc *t = malloc (sizeof *t); /* allocate */
if (t == NULL) { /* validate */
perror ("malloc-t");
return NULL;
}
t->c = "hello"; /* assign on success */
return t; /* return pointer to allocated struct */
}
int main (void) { /* void main only valid in freestanding environment */
struct abc *k = abc(); /* declare and initialize k */
if (k) { /* validate k not NULL */
puts (k->c);
free (k); /* don't forget to free what you allocate */
}
}
Don't forget to validate the return...
(the output is the same)
Proper Declaration for main()
is int main()
Unless in a Freestanding Environment
Unless you are programming in a freestanding environment (without the benefit of any OS), in a standards conforming implementation, the allowable declarations for main
for are int main (void)
and int main (int argc, char *argv[])
(which you will see written with the equivalent char **argv
). See: C11 Standard - §5.1.2.2.1 Program startup(p1). See also: What should main() return in C and C++?
In a freestanding environment, the name and type of the function called at program startup are implementation-defined. See: C11 Standard - 5.1.2.1 Freestanding environment
Look things over and let me know if you have further questions.