简体   繁体   中英

When to malloc() memory for an array inside a struct

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.)

  1. Which way is correct?
  2. What if the argument const char* name is no longer a string literal, but an arbitrary array with length determined at runtime?
  3. 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 )?
  4. 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 ?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM