As far as your actual question:
How can I allocate heap space for the str pointer?
What you've done (x->str = (char*)malloc(sizeof(char*));
) probably isn't what you want. sizeof(char*)
is most likely 4 or 8 depending on your system, but more importantly is unrelated to the char
object(s) that x->str
will point to. When allocating dynamic memory, the general paradigm is to allocate space for the type "one level up" from the lvalue you're assigning to, as a combination of the sizeof
that type and the amount of space desired. That is, for some type T
, you want to allocate space in the following manner:
// pseudo code
T* myPointerToT = malloc(sizeof(T) * numberOfTObjectsIWant);
Here, myPointerToT
is a T pointer type (T*
). "One level up" is a type T
, and so this is what you want to feed to sizeof
. A T*
type should point to T
objects, so you must allocate enough size for the number of T
objects you need.
One more thing, rather than using T
in sizeof(T)
, the preferred syntax is to use the dereferenced variable name. In the example above, that would be *myPointerToT
, changing the line to:
T* myPointerToT = malloc(sizeof(*myPointerToT) * numberOfTObjectsIWant);
The reason for this less maintenance down the road. Imagine T
is a char
, and sometime later, this changes to int
. We now have to change T
in two places:
char* myPointerToT = malloc(sizeof(char) * numberOfTObjectsIWant);
changes to
int* myPointerToT = malloc(sizeof(int) * numberOfTObjectsIWant);
whereas if we started with
char* myPointerToT = malloc(sizeof(*myPointerToT) * numberOfTObjectsIWant);
we now only have to change T in one place:
int* myPointerToT = malloc(sizeof(*myPointerToT) * numberOfTObjectsIWant);
Note, sizeof
is a compile-time operator, so *myPointerToT
isn't really dereferencing anything; the preprocessor can look at that and determine the type, which is what sizeof
needs.
In your case, x->str
is a char*
type, so you want to allocate space for at least a single char
object.
// as stated in another answer, no need to cast malloc return value
x->str = malloc(sizeof(char));
// or
x->str = malloc(sizeof(*(x->str)));
In practice, allocating space for a single char
is foolish, and as indicated by your variable name, this is meant to be a string, so you'll want multiple char
s:
x->str = malloc(sizeof(char) * numOfCharsIWant);
Furthermore, the C standard defines sizeof(char)
to be 1, so this can be omitted as well:
x->str = malloc(numOfCharsIWant);
Finally, you should only dynamically allocate memory if you "have" to, which in practice usually boils down to:
- You won't know how much memory you'll need until runtime
- You need "a lot" of memory. What "a lot" means depends on your system, but in my experience the default stack size for each execution thread on desktop linux is 8MB, which is plenty of space for usual operations.
If you have a general idea what your max string size will be, you could bypass the dynamic memory allocation all together do something like the following:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LENGTH 30 // "small enough"
typedef struct {
int num;
char str[MAX_STR_LENGTH];
} NumStr;
int main(void)
{
// a single object, keep it in automatic storage
NumStr x;
x.num = 3;
strcpy(x.str, "hello")
printf("%d: %s\n", x.num, x.str);
// no need to clean up dynamically allocated memory, since there is none
return 0;
}