Reputation: 1861
There's a struct
struct Foo{
int a, b, c;
char* name;
};
with an initialization function
Foo_init(struct Foo* foo, const char* name){
// ... stuff
}
When I create a struct Foo
object, I pass in a const char*
, to serve as the object's name. Example:
struct Foo foo1;
Foo_init(&foo1, "foo1");
The goal is to "store" the content of "foo1"
into foo1
's char*
variable.
I'm currently doing it like:
Foo_init(struct Foo* foo, const char* name){
foo->name = name;
// ... other stuff
}
but I wonder if the correct way is:
Foo_init(struct Foo* foo, const char* name){
int name_len = strlen(name) + 1;
foo->name = malloc(name_len);
memcpy(foo->name, name, name_len)
// ... other stuff
}
(I suppose either way is fine, since in this example the argument "foo1"
is a string literal.)
const char* name
is no longer a string literal, but an arbitrary array with length determined at runtime?Foo_init()
is not Foo_init(struct Foo* foo, const char* name)
but Foo_init(struct Foo* foo, char* name)
(ie. the char*
is no longer const
)?malloc()
/memcpy()
memory for an incoming argument that is a char*
(or an int*
, or anything that owns a bunch of elements in memory), assuming I want "store it" inside a struct
?Upvotes: 2
Views: 89
Reputation: 6465
Which way is correct?
It depends on usecase, but highly prefer second. If you would store a pointer to string literal to name
and then tried to modify its content, it would lead to undefined behavior. If name
was const
, and you would just need to store this string
without modification, you could use first.
A common technique is for string
literals to be put in "read-only-data" section which gets mapped into the process space as read-only (which is why you can't change it). It does vary by platform.
What if the argument const char* name is no longer a string literal, but an arbitrary array with length determined at runtime?
Doesn't matter, it will be the same. If its string
(null terminated sequence of characters), strlen
will return number of characters and you can copy it to malloced memory on heap
.
What if the signature of Foo_init() is not Foo_init(struct Foo* foo, const char* name) but Foo_init(struct Foo* foo, char* name) (ie. the char* is no longer const)?
It's no longer const
. It allows you to modify content of an array. Since you dont need to modify it (it's init function), you should leave it const
.
More generally, when do I need to malloc()/memcpy() memory for an incoming argument that is a char* (or an int*, or anything that owns a bunch of elements in memory), assuming I want "store it" inside a struct?
You need allocate memory with dynamic storage duration on heap when you dont know amount of input data and need to calculate it in runtime. Automatic arrays are safer & faster so if you dont have to use dynamic storage, dont.
Upvotes: 3