8

Let's say you have-

struct Person {
    char *name;
    int age;
    int height;
    int weight; 
 };

If you do-

struct Person *who = malloc(sizeof(struct Person));

How would C know how much memory to allocate for name variable as this can hold a large number of data/string? I am new to C and getting confused with memory allocation.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
Sajal Dutta
  • 18,272
  • 11
  • 52
  • 74
  • Don't try to write multi-language source files. I believe the idiomatic way to manage memory in C++ is with [RAII](http://en.wikipedia.org/wiki/RAII). – pmg Jan 31 '12 at 14:38
  • 1
    No, `name` is just a pointer, which has a distinct size (usually 4 or 8 bytes). Once you realize this, you got it. – Christian Rau Jan 31 '12 at 14:46

10 Answers10

4

It won't know, You will have to allocate memory for it separately.

struct Person *who = malloc(sizeof(struct Person));

Allocates enough memory to store an object of the type Person.
Inside an Person object the member name just occupies a space equivalent to size of an pointer to char.
The above malloc just allocates that much space, to be able to do anything meaningful with the member pointer you will have to allocate memory to it separately.

#define MAX_NAME 124
who->name = malloc(sizeof(char) * MAX_NAME);

Now the member name points to an dynamic memory of size 124 byte on the heap and it can be used further.

Also, after your usage is done you will need to remember to free it explicitly or you will end up with a memory leak.

free(who->name);
free(who); 
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 4
    I assume the Q is invalidly tagged `C++` since the OP says *How would C....* and *I am new to C...* If the Q is C++, the answer is pretty similar to use an `std::string`. – Alok Save Jan 31 '12 at 14:38
  • I tagged it C++ because I believe they have similarity when it comes to Memory Management. Or am I wrong? I am new to C but not new to programming in general. Thanks for the super quick response. – Sajal Dutta Jan 31 '12 at 14:41
  • 2
    @ZiG There are indeed similarities (although you would rather use `new` over `malloc`). But in C++ you often just don't have to mess with any low-level memory management, e.g. by using `std::string` for strings, instead of plain char arrays (or pointers), or by using `std::vector` instead of self-made dynamic arrays. – Christian Rau Jan 31 '12 at 14:49
  • @Zig And don't forget to +1 the answer if you found it that good to accept it. – Christian Rau Jan 31 '12 at 15:09
  • `You will have to allocate memory for it separately.` Wrong. It's the _pointee_ you're allocating memory for. `name`'s memory is just fine. – Lightness Races in Orbit Jan 31 '12 at 15:26
4

Don't assume that the memory storing the pointer for name is the same as the memory storing the data for name. Assuming a 4 byte word size, you have the following:

  • char * (4 bytes)
  • int (4 bytes)
  • int (4 bytes)
  • int (4 bytes)
  • ================
  • total: 16 bytes

which is: sizeof(char*) + sizeof(int) + sizeof(int) + sizeof(int). C knows the size because you've told it the size of the elements in the struct definition.

I think what you are confused about is the following:

The contents at the char * will be a memory location (e.g. 0x00ffbe532) which is where the actual string will be stored. Don't assume that the struct contents are contiguous (because of the pointer). In fact, you can be pretty sure that they won't be.

So, to reiterate, for an example struct Person (this is just an example, the locations won't be the same in a real program.)

  • location : [contents]
  • 0x0000 : [0x00ffbe532]
  • 0x0004 : [10]
  • 0x0008 : [3]
  • 0x000C : [25]

  • 0x00ffbe532 : [I am a string\0]

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Liam
  • 92
  • 9
2

The name member is just a pointer. The size of a pointer varies with the underlying architecture, but is usually 4 or 8 bytes nowadays.

The data that name can point to (if assigned later) should be laid out in an area that does not coincide with the struct at all.

At the language level, the struct doesn't know anything about the memory that the name member is pointing to; you have to manage that manually.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
2

It allocates memory for the just the pointer to a char. You need to do a separate allocation for the contents.

There are other options although:

If you are OK with having a fixed sized maximum length, you can do:

struct Person {
    char name[PERSON_NAME_MAX_LENGTH+1];
    int age;
    int height;
    int weight; 
 };

And allocate it as in your example.

Or you can declare a variable sized struct, but I wouldn't recommend this as it is tricky and you cannot have more than one variable size array per struct:

struct Person {
    int age;
    int height;
    int weight; 
    char name[]; /*this must go at the end*/
 };

and then allocate it like:

struct Person *who = malloc(sizeof(struct Person) + sizeof(char)*(name_length+1));
Community
  • 1
  • 1
fortran
  • 74,053
  • 25
  • 135
  • 175
1

It will allocate 4 bytes for the name pointer, but no space for the "real" string. If you try to write there you will seg fault; you need to malloc (and free) it separately.

Using string (in C++) can save you some headache

Jakub M.
  • 32,471
  • 48
  • 110
  • 179
1

For pointers the struct is allocated enough memory just for the pointer. You have to create the memory for the char* and assign the value to the struct. Assuming you had char* name somewhere:

struct Person *who = malloc(sizeof(struct Person));
who->name = malloc((strlen(name)+1) * sizeof(char));
strcpy(who->name, name)
Matt Esch
  • 22,661
  • 8
  • 53
  • 51
0

It doesn't. You have to do that too.

struct Person *who = malloc(sizeof(struct Person));
who->name = malloc(sizeof(char) * 16); /* for a 15+1 character array */
Kaz Dragon
  • 6,681
  • 2
  • 36
  • 45
0

You have a pointer to a name character array in your struct, ie. it will consume that much bytes that are needed to represent a memory address.

If you want to actually use the field, you must allocate additional memory for it.

Abrixas2
  • 3,207
  • 1
  • 20
  • 22
0

Pointer members occupy one word in my experience (the address on witch the data actually resides) so the size will probably be 16 bytes (assuming one word is 4 bytes)

As the man said above you need to separately allocate memory for *name witch will free memory someplace else for the size you desire

omu_negru
  • 4,642
  • 4
  • 27
  • 38
-2

I think you should also need to allocate memory for the name attribute

aacanakin
  • 2,844
  • 4
  • 25
  • 42