Allocating a person structon the heap?


#1

The first part of The Heap chapter makes perfect sense to me when you were talking about making a chunk of memory available for 1,000 floats using the pointer startOfBuffer such as:

However, I don’t think there was enough explanation on allocating enough memory for structs. The code sample was confusing and the explanation and use of the -> operator had me dumbfounded. Is there a simpler explanation you could provide for allocating memory for structs? I’m also not clear with what the -> operator does.

#include <stdio.h>
#include <stdlib.h>

typedef struct {
float heightInMeters;
int weightInKilos;
} Person;

float bodyMassIndex(Person *p)
{
return p->weightInKilos / (p->heightInMeters * p->heightInMeters);
}

int main(int argc, const char * argv[])
{
// Allocate memory for one Person structure
Person *x = (Person *)malloc(sizeof(Person));

// Fill in two members of the structure
x->weightInKilos = 81;
x->heightInMeters = 2.0;

// Print out the BMI of the original Person
float xBMI = bodyMassIndex(x);
printf("x has a BMI of = %f\n", xBMI);

// Let the memory be recycled
free(x);

// Forget where it was
x = NULL;

return 0;
}

Thank you in advanced. I want to make sure I understand this before moving onto objects which I realize will rely heavily on structs.


#2

So, a Person struct takes up a certain amount of memory. So, we ask malloc() for that many bytes, and we get back the address where those bytes live. We store that address in the pointer. Here is that as two lines:

Person *x; x = malloc(sizeof(Person));
(To get rid of a compiler warning, we do an explicit cast to (Person *), but I left that out for simplicity)

If you have a struct, you use the period to access members:

If you have a pointer to a struct, you use the -> operator:

I think you are probably over-thinking this. Just move on to the next chapter and come back after you finish the book.


#3

Ok I see… But in the same code, I’m a little confused by two things:

float bodyMassIndex(Person *p) { return p->weightInKilos / (p->heightInMeters * p->heightInMeters); }

… We are using the functions return statement, but isn’t the point of using return so you don’t need to use a pointer unless you are returning more than one value?

I still don’t see why *p is necessary and p-> instead of p and say, p.heightInMeters since we are using return

The other thing is code, and to make sure I’m understanding what’s going on:

Normally wouldn’t a pointer require an & “addressof”? I’m assuming malloc() does that job without the need of &? Am I correct in assuming & is for an addressof a location only on the stack? and malloc() is for creating enough memory on the heap, not the stack AND returning the "addressof "to the pointer?

Thanks!!


#4

I can see how you might arrive at that conclusion, but that’s not really what’s going on.

Aaron’s advice was solid: I’d definitely recommend coming back to this later. Pointers are an extremely hairy topic, and the need to do anything other than pass messages to objects stored in pointers is rare in Objective-C, so far as I can tell, so while this chapter is necessary to do serious programming, it’s not necessary at this point in the material to understand it.

There’s a fantastic book on the inner workings of C that I’d recommend if you want an entertaining look at an otherwise deadly dry topic. Expert C Programming: Deep C Secrets by Peter van der Linden is one of the best books on programming that I’ve ever encountered.

I did a quick search for pointer tutorials, and wasn’t impressed. I may make an attempt, but explaining pointers well is vastly harder than understanding them.


#5

So, this line:

says “the function bodyMassIndex() expects a pointer to a Person struct as an argument and returns a float”

This line:

Can be broken into two lines:

Person *x; // Declare a variable x that holds the address of a Person struct
x = (Person *)malloc(sizeofPerson)); // Get a Person-sized chunk of memory from the heap

#6

Hi,

I am still confused:

(…)
Person *x = malloc(sizeof(Person));

x->weightInKilos = 81;
x->heightInMeters = 2.0;

(…)

works as well as if I cast “Person *x = (Person *)malloc(sizeof(Person));”

I would appreciate anyway a syntax explanation.

malloc() returns void by default, by putting “(Person *)” (which is a pointer to an address which stores an Person struct(ure) ) in front of it I advise malloc() to return a Pointer ?

Is that correct ?

I didn’t find a explanation on the web for malloc() which explains this at beginner level …

Thanks!


#7

malloc returns a void pointer, not void. Significant difference.

In C, a void pointer is an address in memory with no defined content type. malloc gives you some memory and it’s up to you to decide what it should hold.

By adding (Person *) to the code, you’re telling the compiler that you want to treat the memory as a Person object. This achieves two useful purposes, neither of which impact the underlying machine code that will be generated:

[ul][li]If you accidentally try to assign it to something that isn’t compatible with a Person object, the compiler can warn you.[/li]
[li]Someone reading your code later knows what you’re intending.[/li][/ul]


#8

Hi,

thanks a lot for the explanation (which should make it to the book :slight_smile: )!

So casting the type to malloc() is optional, correct ?

Thanks

Klaus


#9

Unless I’m forgetting something, yes, it’s optional.