C: malloc() doesn't just allocate memory

  • Thread starter nobahar
  • Start date
  • Tags
    Memory
In summary: you assign space in memory using malloc() it would simply set aside that space, but by assigning the space to a pointer which is "set-up" to point to a happy-type structure, the space is "partitioned" to match the structure and its members: happy has members that perform specific functions, e.g. a pointer, this means the space in memory for this pointer has to be known to be separate from the other member, int x, and to be of type pointer.
  • #1
nobahar
497
2
Hello,

Another (probably obvious) question:
malloc() assigns memory space in bytes; e.g. malloc(100) assigns 100 bytes of space and returns a pointer.

However, in creating a linked list, I can allocate space a assign it to a pointer and the structure already exists?
For example:
Code:
//Create structure
struct happy
{
     int x;
     struct happy *h_ptr;
};

int main( void )
{
     //Pointers for assigning head to link to first structure and a pointer for creating new links
     struct happy *head = NULL;
     struct happy *newlink = NULL;
     
     //Assign memory for structure and assign address of space to head pointer
     head = malloc(sizeof(struct happy));

     //Make the pointer in happy, h_ptr, point to NULL, since it is the last (and only) element
     head->h_ptr = NULL;

     ...
     return 0;
}

If malloc() only assigned space in memory, then why does head->h_ptr = NULL work? malloc() set aside the correct amount of space, but it doesn't "know" what for, the structure type hasn't been placed there. Does the pointer type - that malloc is set to point to a structure of type happy - mean that the structure type is created because of the pointer? I have seen typecasts, e.g. head = (struct happy *)malloc(sizeof(struct happy)), used, but also read that they are not necessary in C. If the typecast was used, I can imagine that it tells the malloc() function to "divide up" the space into a happy structure type; does the pointer type, by pointing to a happy structure type, do the same thing?

Any help appreciated,
Thanks in advance.
 
Technology news on Phys.org
  • #2
malloc returns a void* pointer. A type cast is not needed because void* converts to any pointer type without a cast -- in C, that is. This is not the case in C++ (but you should never use malloc in C++).

It doesn't hurt to add the cast; it doesn't cost anything. A typecast results in zero assembly code when converting from one pointer type to another.
 
  • #3
In a way the structure of happy is "always there".

Pointer is just an address of a place in memory. Structure definition tells your program how to treat whatever data happens to be at the address variable sits in memory. You don't have to do anything for the structure to "exist". However, you have to initialize it with a correct data if you want the structure to make sense in your program. Memory allocated by malloc() can contain anything, and the content may even accidentally make sense.

Note: depending on the complier and mode it is working in, allocated memory can be either completely random, or initialized with some values (like 0xCDCDCDCD). This often makes debugging easier, but it sometimes means release version of the code behaves differently than the debug version (which usually means you forgot to initialize something in your code, and the debug version worked correctly by accident).
 
  • #4
D H said:
A type cast is not needed because void* converts to any pointer type without a cast

Is it in any way accurate to understand this to mean something like the following:

I have my structure happy as before.

I declare a pointer that points to a structure of type happy.
Code:
struct happy *h_ptr = NULL;

When I assign space in memory using malloc() it would simply set aside that space, but by assigning the space to a pointer which is "set-up" to point to a happy-type structure, the space is "partitioned" to match the structure and its members: happy has members that perform specific functions, e.g. a pointer, this means the space in memory for this pointer has to be known to be separate from the other member, int x, and to be of type pointer. Its not simply setting aside, say, 12 bytes, but 4 for int and 8 for the pointer. I can immediately use the memory set aside as though this partition exists:
Code:
head = malloc(16);
head->h_ptr = NULL;
If on the other-hand I declared malloc(16), and assigned the return value to a char * pointer, it would set-aside the correct space for a string, and
Code:
head->h_ptr = NULL;
would not work.

I hope this makes sense; if so, is it in anyway accurate?
Thanks borek and DH for the help so far.
 
  • #5
nobahar said:
by assigning the space to a pointer which is "set-up" to point to a happy-type structure, the space is "partitioned" to match the structure and its members

No, it is not. That's what I tried to tell you. "Space partitioning" is defined by the structure definition. malloc doesn't care about internal structure, all it does is it allocates sizeof(happy) bytes. It will do exactly the same operation for every other structure that happens to occupy exactly the same number of bytes.

nobahar said:
If on the other-hand I declared malloc(16), and assigned the return value to a char * pointer, it would set-aside the correct space for a string, and
Code:
head->h_ptr = NULL;
would not work.

You can easily make it work by casting a pointer. There is no such thing as a "correct space for string", there are 16 bytes of memory.
 
  • #6
nobahar said:
the space is "partitioned" to match the structure and its members

No operation needs to be done when the program is running for this "partitioning".

happy has members that perform specific functions, e.g. a pointer, this means the space in memory for this pointer has to be known to be separate from the other member, int x, and to be of type pointer. Its not simply setting aside, say, 12 bytes, but 4 for int and 8 for the pointer.

That is correct, and that is known to the compiler when the program is compiled. A structure is a contiguous block of memory starting at some address x. The compiler knows that field a is at a fixed offset from the beginning of the structure, and it knows that field b is at another fixed offset from the beginning of the structure. So your expression "x->a" is compiled to something like "take address from variable x and add offset_a bytes to it; this is the address where the field is". Likewise, "x->b" is compiled to "take address from x and add offset_b bytes to it; this is the address where the field is". offset_a and offset_b are compile-time constants (you could even obtain them with some creative use of C).

The point of that is NOTHING needs to be done to the memory allocated by malloc() to use it as a structure.

This is markedly different in C++. In C++, something MAY need to be done; this is why malloc() is deprecated in C++ and operator new should be used whenever possible.
 
  • #7
voko said:
The point of that is NOTHING needs to be done to the memory allocated by malloc() to use it as a structure. This is markedly different in C++. In C++, something MAY need to be done; this is why malloc() is deprecated in C++ and operator new should be used whenever possible.
Whether something needs to be done or not normally depends on the structure (or class), not if it's C or C++. In this case, a pointer within the structure needs to be initialized to NULL. In C++, this is done via "constructor" code for the struct or class, in C, it needs to be done "manually" in code every time a new instance of a struct is allocated, and a function to allocate and initialized a struct could be used if wanted.
 
  • #8
rcgldr said:
Whether something needs to be done or not normally depends on the structure (or class), not if it's C or C++.

In C, a structure needn't be initialized to be used. That's not part of the language spec.

In C++, non-POD classes need initialization, which is part of the language spec.

In this case, a pointer within the structure needs to be initialized to NULL.

No. This is up to the programmer. It makes sense, ordinarily, but that is not a requirement.

In C++, this is done via "constructor" code for the struct or class

Even in C++ it is perfectly fine not to initialize members which are POD.
 
  • #9
Borek said:
You can easily make it work by casting a pointer. There is no such thing as a "correct space for string", there are 16 bytes of memory.

I should have tried this earlier; I didn't have the confidence because I wouldn't be happy that what I did was a correct method to test anything! I decided to assign the address returned from malloc() to a char * pointer and then assign the address from the char * pointer to the struct pointer and then proceed from there, accessing the structure's pointer. I think this is a correct test.

voko said:
No operation needs to be done when the program is running for this "partitioning".



That is correct, and that is known to the compiler when the program is compiled. A structure is a contiguous block of memory starting at some address x. The compiler knows that field a is at a fixed offset from the beginning of the structure, and it knows that field b is at another fixed offset from the beginning of the structure. So your expression "x->a" is compiled to something like "take address from variable x and add offset_a bytes to it; this is the address where the field is". Likewise, "x->b" is compiled to "take address from x and add offset_b bytes to it; this is the address where the field is". offset_a and offset_b are compile-time constants (you could even obtain them with some creative use of C).

The point of that is NOTHING needs to be done to the memory allocated by malloc() to use it as a structure.

This is markedly different in C++. In C++, something MAY need to be done; this is why malloc() is deprecated in C++ and operator new should be used whenever possible.

Thanks voko, I appreciate Borek's response - it certainly helped - but yours is what made it "click"! Many thanks!
 

FAQ: C: malloc() doesn't just allocate memory

What is the purpose of the C "malloc()" function?

The "malloc()" function in C is used to dynamically allocate memory during program execution. It reserves a specific amount of memory space in the heap and returns a pointer to the beginning of the allocated memory. This allows for more efficient use of memory and greater flexibility in program design.

Does "malloc()" only allocate memory?

No, the "malloc()" function not only allocates memory but also initializes the allocated memory to a default value of 0. This ensures that the memory allocated by "malloc()" is not filled with any previously stored data, reducing the risk of bugs and errors in the program.

What happens if "malloc()" fails to allocate memory?

If the "malloc()" function fails to allocate memory, it will return a NULL pointer. This indicates that there is not enough available memory in the heap to fulfill the request. In such cases, it is important to handle the error gracefully and free any previously allocated memory to prevent memory leaks.

How does "malloc()" differ from "calloc()"?

"malloc()" and "calloc()" are both used to dynamically allocate memory, but they differ in how they handle the allocated memory. "malloc()" only allocates memory, while "calloc()" not only allocates but also initializes the allocated memory to 0. This can be useful when working with arrays or structures.

How can "malloc()" be used to allocate memory for arrays?

To allocate memory for an array using "malloc()", the programmer needs to specify the size of the array in bytes and use the "sizeof" operator to determine the size of each element in the array. The "malloc()" function will then return a pointer to the beginning of the allocated memory, which can be used to access and manipulate the array elements.

Similar threads

Replies
4
Views
3K
Replies
3
Views
1K
Replies
6
Views
7K
Replies
1
Views
9K
Replies
6
Views
2K
Replies
3
Views
909
Back
Top