Let's see if we can't give you a bit of foundation to build from. When you declare s1
, you declare a struct of type struct myStruct
which conveniently has a typedef
to str1
; The declartion:
str1 s1;
creates storage for s1
, which has automatic storage duration and it is valid only while s1
remains in scope. The automatic storage for s1
includes storage for one pointer array
and nothing else. (ignoring padding for the moment). The one pointer array
is completely unintialized, and points to some indeterminate address which you do NOT have the ability to write to. Attempting to write to an uninitialized value invokes Undefined Behavior and the valid operation of your program ceases at that point. (in fact attempting to write to it will likely result in a Segmentation Fault)
How do you create storage for s1.array
? Here is where you need to allocate. (before you attempt to copy to s1.array
) How much memory is required to store your string? strlen(string) + 1
(the +1 to provide storage for the nul-terminating character)
Knowing that, and having followed the link I left in the comment, you can allocate storage for your string with:
s1.array = malloc (strlen ("Damn") + 1);
For every allocation, you will validate the allocation succeeded before attempting to use the block of memory. If malloc
fails (and it does), you attempting to use the invalid block puts you right back where you would have been if you failed to allocate at all -- straying off into Undefined Behavior...
Now you have initialized s1.array
to point to a valid block of memory and you have validated the allocation succeeded, you can now copy your string to s1.array
.
strcpy (s1.array, "Damn");
Your display
function need allocate nothing (you can of course). Your display
function need only display the string that is now held in s1.array
. As Jonathan Leffler mentioned, you can simply pass a pointer to display(str1 *s)
and then output s->array
from within. Nothing more needed than:
void display (mystruct_t *s)
{
printf ("%s\n", s->array);
}
which you will call from main()
as:
display (&s); /* pass the address of s (a pointer to s) */
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.
When you return from display()
the use of s1.array
is over and it can be freed. Get in the habit now of freeing the memory you allocate and don't simply rely on it being freed when the program ends -- this will pay dividends as your code become more complex. Simply,
free (s1.array); /* if you allocate it, you free it when done */
And since s1
has automatic storage, there is nothing to free for the structure itself.
Let's leave you with two examples. The first will declare the structure with automatic storage duration and only allocate for s.array
(as was discussed above). The second will declare a pointer to your struct now requiring you to allocate for both the structure and array. (which in turn requires you to free both the array and structure)
Structure with Automatic Storage Duration
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR "Damn"
typedef struct mystruct {
char *array;
} mystruct_t;
void display (mystruct_t *s)
{
printf ("%s\n", s->array);
}
int main (void) {
mystruct_t s; /* struct with automatic storage - for the pointer */
/* s is a struct, so you use the '.' operator access members */
s.array = malloc (strlen (STR) + 1); /* you must allocate for array */
if (s.array == NULL) { /* validate each allocation */
perror ("malloc-s.array");
return 1;
}
strcpy (s.array, STR); /* with valid memory pointed to, you can copy */
display (&s); /* pass the address of s (a pointer to s) */
free (s.array); /* if you allocate it, you free it when done */
return 0;
}
Declaring a Pointer to struct
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR "Damn"
typedef struct mystruct {
char *array;
} mystruct_t;
void display (mystruct_t *s)
{
printf ("%s\n", s->array);
}
int main (void) {
mystruct_t *s; /* declare a pointer to the struct itself */
s = malloc (sizeof *s); /* now you must allocate for the struct */
if (s == NULL) { /* and you validate every allocation */
perror ("malloc-s");
return 1;
}
/* s is a pointer to struct, so you use -> to reference member */
s->array = malloc (strlen (STR) + 1); /* you must allocate for array */
if (s->array == NULL) { /* validate each allocation */
perror ("malloc-s->array");
return 1;
}
strcpy (s->array, STR); /* with valid memory pointed to, you can copy */
display (s); /* s is a pointer, just pass it to display */
free (s->array); /* if you allocate it, you free it when done */
free (s); /* don't forget to free the struct */
return 0;
}
(In both cases the output is simply your string)
Look over both paying careful attention to the use of the '.'
or ->
operators to dereference the structure and access array
. You need to understand when and where to use them both.
Let me know if you have further questions.