The core reason for returning a pointer from Person_create is that it is returning memory that has been dynamically allocated with malloc. The only way you can track dynamic memory in C is through a pointer value.
I really have problems understanding the whole concept of pointers and when you should use them.
What are pointers?
Conceptually, pointers are simple beasties; any expression that evaluates to the location of an object in memory is a pointer. Given the declaration
int x;
then the expression &x is a pointer - it evaluates to the address of the variable x. You can store pointer values in variables of pointer type:
int *p = &x;
Now p is also a pointer expression, since it will evaluate to the address of x.
Pointer declaration syntax can be a little confusing. Declarations in C are based on the types of "expressions", not objects. Given a pointer to an integer named p, you access the integer value by deferencing p with the unary * operator:
q = *p;
The type of the expression *p is int, so it follows that the declaration of p is
int *p;
You could write it as int* p, but it will be parsed as int (*p); the * is always bound to the declarator, not the type specifier.
Pointer expressions have type information associated with them; a pointer to int is a different type from a pointer to double, which is a different type from a pointer to char, etc. This matters for pointer arithmetic; p + 1 will give a different result if p is a char * or an int *, because it gives you the address of the next instance of the pointed-to type.
When do I use them?
C requires you to use pointers in two cases. The first is when you are tracking dynamically allocated memory, as above. The second is when you want a function to write to its parameters, and have those changes reflected in the caller. Think about a library function like scanf:
int x;
...
scanf( "%d", &x );
You want scanf to write something to x, so you must pass a pointer to x.
The one monkey wrench in this is array expressions; under most circumstances, an expression of type "N-element array of T" will be converted to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. That's why you don't use the & operator when calling scanf on an array of char:
char buf[N];
scanf( "%s", buf );
Under this circumstance, the expression buf is converted to a pointer type automatically, and using & in this instance would be a mistake.
Pointers have a number of other uses, though; you'll typically see them used to iterate through an array, or to build dynamic data structures, or to identify substrings in a larger string, stuff like that.