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() )
Using C++ we will identify the memory region of an object by declaring a new variable and compare this variable from the object that we wanted to identify. If the address of an object is in close proximity to the new variable then they are in the same region. This solution is accurate only for non multi threaded system or large project as I only assume 1000 bytes or 250 pointer variables gap from the new variable to the object we are comparing.
class ObjectDiagnostic {
public:
static int obj_alive;
ObjectDiagnostic(string name) {
++obj_alive;
std::cout << "Name: " << name << " located in " << getMemLocation() << std::endl;
}
const char* getMemLocation() {
int* p = new int(1); //heap variable
const char* memAlloc = "HEAP";
if (((&p - (void*)this) * -1) < 1000) {
memAlloc = "STACK";
}
return memAlloc;
}
}
int main() {
ObjectDiagnostic() objD = ObjectDiagnostic("objD"); //stack object
ObjectDiagnostic() *objD2 = new ObjectDiagnostic("objD2"); //heap object
}
The most accurate one is to use the assembly and access the current stack pointer.
asm("mov %%rsp, %0" : "=rm" (stackpointer))
and use that as the reference rather than declaring a variable as reference.
C++ Using STL reverse
int main(int argc, char *argv[])
{
int a[] = { 4, 5, 6, 7 };
std::cout << "Int Array" << endl << "original: ";
for (auto e : a) std::cout << e;
std::cout << endl;
std::cout << "reverse: ";
std::reverse(std::begin(a), std::end(a));
for (auto e : a) std::cout << e;
std::cout << endl;
std::string name = "DRAGON";
std::cout << "String" << endl << "original: " << name << endl;
std::reverse(std::begin(name), std::end(name));
std::cout << "reverse: ";
for (auto e : name) std::cout << e;
std::cout << endl;
int* ip;
int n = 9;
ip = &n;
std::cout << "Pointer Values" << endl << "original: " << ip << endl;
std::stringstream ss;
ss << ip;
std::string address = ss.str();
std::reverse(std::begin(address), std::end(address));
std::cout << "reverse: ";
for (auto e : address) std::cout << e;
std::cout << endl;
return 0;
}
Output:
Int Array
original: 4567
reverse: 7654
String
original: DRAGON
reverse: NOGARD
Pointer Values
original: 0115FB40
reverse: 04BF5110