What is the difference between reference and address in C?
An address is a number that corresponds to a place in memory.
A reference is a name that refers to an existing object, rather than being it's own object.
What makes them different?
int x;
int & r = x;
Explained:
int x = 7 ; // x is an object of type int
// x has an address (of type pointer to int)
// an object is a region of storage that has a size, a type, and a lifetime
// this object was created by the definition of the variable x of type int
int& r = x ; // r is a variable, but it is not an object
// the variable r refers to (is an alias for) the the object x.
// r has no address of its own; and it may not occupy any storage at all
// r is an alias for x, and &r yields the address of x
// (references are not objects; we can't have arrays of references)
// (references are not objects; we can't use new to allocate a reference)
int* p = &x ; // p is an object of type pointer to int (initialised with the address of x)
// p is an object; it has an address of type pointer (pointer to int)
// p is a region of storage that has a size, a type, and a lifetime
// this object was created by the definition of the variable of type pointer to int
How about this?
int myfun();
int & myfun();
Explained:
With int myfun();, the expression myfun() yields a prvalue (a pure rvalue).
A prvalue either identifies a temporary object or, as in this example, a value that is not associated with any object.
With int& myfun();, the expression myfun() yields an lvalue.
That lvalue identifies a non-temporary object of type int.
int fn1() { return 67 ; } // fine
int fn2() { int i = 6 ; return i ; } // fine.
// the lifetime of the local objct i is over once the function returns.
// but we are not returning the object i; we are returning a prvalue initialised with i
int& fn3() { return 67 ; } // *** error: 67 is not an lvalue
int& fn4() { int i = 6 ; return i ; } // *** logical error: we are returning an lvalue
// but the lifetime of the local objct i is over once the function returns.
int& fn5() { static int i = 6 ; return i ; } // fine: lifetime of i extends beyond the return
fn1() = 23 ; // *** error: can't assign to rvalue
fn5() = 23 ; // fine: assign to lvalue ( assign to static int i in fn5() )