struct Point { int x; int y; }; void init_point(struct Point *p); struct Point new_point(); void f() { struct Point p1, p2; init_point(&p1); p2 = new_point(); // equivalent, potentially slower } void init_point(struct Point *p) { p->x = 0; (*p).y = 0; } struct Point* dangling_point() { struct Point ans; ans.x = 0; ans.y = 0; return &ans; // really bad idea! } struct Point new_point() { struct Point ans; ans.x = 0; ans.y = 0; return ans; // no problem } void wrong_update_x(struct Point p, int new_x) { // this function has no effect on anything p.x = new_x; } void update_x(struct Point * p, int new_x) { p->x = new_x; }