0

I have this struct:

struct foo {
  char *a;
  char *b;
  char *c;
  char *d;
};

it's possible allocate space for struct itself and its members instead of e.g,

struct foo f;
f.a = malloc();
f.b = malloc();
f.c = malloc();
f.d = malloc();
strcpy(f.a, "a");
strcpy(f.b, "b");
//..

something like this(of couse that it doesn't works):

struct foo f = malloc(sizeof(struct f));
strpcy(f.a, "a");
//etc
Jack
  • 16,276
  • 55
  • 159
  • 284

4 Answers4

4

You can certainly allocate memory for the struct itself and its members in one go, if that's what you're asking. You just have to know how much you're going to need it (in total) and take care of any possible alignmentation issues (not present in this particular case, though).

struct foo *f = malloc(sizeof *f + size_a + size_b + size_c + size_d);
f.a = (char*)(f + 1);
// ...
eq-
  • 9,986
  • 36
  • 38
1

You can do it if you know all the "dynamic" variable sizes at construction time.

struct foo *f = malloc(sizeof(struct f) + nSizeExtra);

f->a = (char*) (f + 1);
f->b = ((char*) (f + 1)) + nLengthOfA;
f->c = ((char*) (f + 1)) + nLengthOfA + nLengthOfB;
f->d = ((char*) (f + 1)) + nLengthOfA + nLengthOfB + nLengthOfC;

Of course at the end you should free only f (not its members)

valdo
  • 12,632
  • 2
  • 37
  • 67
1

Of course you can allocate memory for your struct and it's members, but if you allocate one contiguous memory for the whole thing, you will need to initilize your struct's members anyway, so you can't do what you want as easily as you'd like to.

piokuc
  • 25,594
  • 11
  • 72
  • 102
  • Why not? Is there a special reason I don't know? – valdo Sep 02 '12 at 15:29
  • Ok, what I just wrote above is not quite correct, but I think it actually answers on Jack's answer, who wanted to call malloc once and use the struct and it's members as they were properly initilized. If you do what others suggested you need to initialize the members first, anyway. – piokuc Sep 02 '12 at 15:35
1

This is called a constructor. With error handling omitted, it may look like:

struct foo *new_foo()
{
    struct foo *obj = malloc(sizeof(struct foo));
    obj->a = malloc(...);
    obj->b = malloc(...);
    obj->x = new_x(...);
    ...
    return obj;
}

and need a corresponding destructor. If you find yourself needing to write code like this often, it may be time to switch to C++ :).

aib
  • 45,516
  • 10
  • 73
  • 79
  • Very nice. I had forgotten of it. Thanks! but about the designer of this implementation, how do you check for non-NULL values? who should check it, the constructor or caller? after each `malloc()`/`calloc()` call check if the return-value has non-null value, but if is NULL, so free the members previously allocated or the caller? – Jack Sep 02 '12 at 15:52
  • C++ uses exceptions (`bad_alloc`) and RAII for this. Memory allocation failing is a rare case, and often unrecoverable anyway. As for C code, I'd probably go with the constructor doing the checks and `free()`s (or maybe a quit or two :). This function simply exists to make the caller's life easier, anyway; burdening them with error recovery would be against the whole point. – aib Sep 02 '12 at 16:08
  • Though, of course, it is the caller's duty to check the overall return value against `NULL`, unless that's guaranteed not to happen. – aib Sep 02 '12 at 16:09