0

I have a question about ex 16 of learn C the hard way.

There is a function definition at the beginning of the code:

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

struct Person *Person_create(char *name, int age, int height, int weight)
{
    struct Person *who = malloc(sizeof(struct Person));
    assert(who != NULL);

    who->name = strdup(name);
    who->age = age;
    who->height = height;
    who->weight = weight;

    return who;
}

What is the reason that the function is written with a pointer? *Person_create? I really have problems understanding the whole concept of pointers and when you should use them. Can anybody help me?

bmargulies
  • 97,814
  • 39
  • 186
  • 310
Hanna
  • 13
  • 5
  • 4
    "I really have problems understanding the whole concept of pointers and when you should use them" — closing as too broad. – n. m. could be an AI Jun 02 '14 at 15:39
  • 1
    Google "C pointers" and you will get a lot of different explanations about what pointers are and why you would use them. First results I get are a tutorial on c pointers and what they are (http://pw1.netcom.com/~tjensen/ptr/pointers.htm), Pointers in C (http://www.tutorialspoint.com/cprogramming/c_pointers.htm) and lots more that will be able to help. – Phil_12d3 Jun 02 '14 at 15:42
  • Take a look at [this SO question and the answers](http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap/80113#80113). It might help. – R Sahu Jun 02 '14 at 16:31
  • It's written with a pointer because this is the only way you can create an object within a function without having that object cease to exist when that function ends. Programming would be fantastically more difficult if you couldn't do this. The memory you allocate with `malloc()` (unlike the pointer variable `who`, for instance) survives the end of that function, but because none of the *names* declared in that function do, the address of that memory becomes the only way you have to subsequently refer to it, and that's what the function returns. – Crowman Jun 02 '14 at 16:48

4 Answers4

3

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.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • Thanks for the clear answer! I just rewrote the code without pointers, and if I understand correctly the main difference is now that if I create a new struc it is on the stack instead of on the heap. Furthermore, I can not write something to a structure I created. Is this correct? – Hanna Jun 02 '14 at 18:16
0

That code is poorly formatted. The star * in front of Person_create actually applies to the return type. So Person_create() returns a struct Person*.

You can further determine this by checking that the variable returned (who) is of type struct Person*. Note that since memory is dynamically created by Person_create() through the use of malloc(), you must delete that memory using free() when you are done with it.

Daniel
  • 1,920
  • 4
  • 17
  • 35
  • 2
    There are (at least) two camps on the formatting issue. One prefers declarations like `int* p` (since the type of `p` is `int*`), while other likes `int *p;` (since the type of `*p` is `int`) and there are good arguments for each. It's not "poor formatting". – Joshua Taylor Jun 02 '14 at 16:13
0

All that it is saying is it will return a pointer to struct Person type. Following is the breakdown.

  • Person_create : function name
  • struct Person * : return type. This is pointer to struct Person.
  • (char *name, int age, int height, int weight) : function arguments

One reason for functions to return pointers to structs (as in this case) is to avoid copying whole structs which would be slow and resource inefficient.

bytefire
  • 4,156
  • 2
  • 27
  • 36
0

One reason is that a pointer is typically 4 or 8 bytes so it is faster to pass around pointers to a person struct then to copy all the data in it.

David Grayson
  • 84,103
  • 24
  • 152
  • 189