(“Headfirst” means the post on the book [[headfirst C]])
When people say “receive a pointer”, “wild pointer”, “delete a pointer”, “compare two pointers”, “include two pointer members“… a pointer can mean several things. A lot of fundamental issues lie in those subtle differences. (To keep things simple, let’s assume a 32 bit machine.)
1) 32bit Object — a pointer can occupy (heap, stack, global) memory and therefore (by ARM) qualify as a 32bit Object.Note it’s not always obvious whether a given ptr variable has its own 32-bit allocation.
- For example, if a pointer is a field in a C struct or C# struct/class, then it pretty much has to be allocated 32 bits when the struct is allocated.
- For example, if a double pointer p5 points to a pointer p8. Since p8 has an address it must occupy memory so p8 is by definition an object. But p5 may not be an object if without an address.
2) address — in some contexts, a “pointer” can mean an address, and we don’t care the pointer object (if any). An address is pure Information without physical form, perhaps with zero /footprint/. When you pass myfloatPtr + 2 to function(), you are passing an address into function(). This address may not be saved in any 32-bit object. I suspect compiler often uses registers to hold such addresses. Note it’s not always obvious whether a given ptr variable has its own 32-bit allocation.
- For example, in C An array name is always a const-pointer (not ptr-to-const) to an already-allocated array in memory. For an array of 10 doubles, 640 bits are already allocated. However, compiler may not need to allocate 32 bits to hold the array name. The array name like “myArray” is like an alias of an address-of-a-house i.e. pure address not an object.
- For example, in C if I save the address-of-something in a transient, temp variable, compiler may optimize away the stack-allocation of that variable.
- see also headfirst.
Fundamentally, if a symbolic name is permanently attached to an Address-of-a-house (permanent alias?), then compiler need not allocate 32bit of heap/stack/global area for the symbolic name. Compiler can simply translate the name into the address. If the symbolic name rebind to a 2nd address, compiler can still avoid allocating 32 bit for it.
Whether it’s an object or a pure address, a pointer variable is a nickname. Most commonly, a pointer means a pointer variable as in (a) below. Remember a nickname exists in source code as a mnemonic for something but binding is impermanent. When we look at code snippets, we may not know whether a variable is a
- a) nick name for a 32-bit pointer object — most common
- b) or nick name for a pure address. An array-name like myArray in source code is such a nickname — rather confusing. Note there’s no 32-bit pointer object in myArray, beside the actual allocation for the array.
- See also headfirst
A 32-bit pointer Object often has multiple nick names. In general, any object can have multiple nick names. If a nickname is transient or never refers to a 2nd Object, then compiler can optimize it into (b).
—- some implications —-
resource (like a DB) — usually requires some allocation on heap, and we access the resource via a pointer. This pointer could be a pure address, but more commonly we pass it around in a 32-bit object.
“delete this” —– When you delete a pointer, you invoke delete() on an Address, including the controversial “delete this” — The entire Object is bulldozed but “delete this” is fine because “this” is treated as an Address. However, the method that performs “delete this” must ensure the object is not allocated by malloc() and not a nonref field (resident object) “embedded in the real estate” of another heapy thingy object. In the case of multiple inheritance, it must not be embedded in the real estate of a derived class instance. See http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.15.
reference counting —- In reference counting for, say, a shared data structure, we count “handles” on our pointee. Do we count pointer Variables or pointer Objects? I’d say neither — we count Address usage. If a thread has a function1() in its top “frame” and function1() is using our target data structure we must count it and not de-allocate it with a bulldozer. This function1() does not necessarily use any 32-bit pointer object to hold this Address. It might make do without a pointer Variable if it gets this address returned from another function.
vptr and “this” pointers —- The vptr is always a pointer Object taking up 32 bit real estate in each instance (java/c# classes and Polymorphic C++ classes). How about the “this” pointer? Probably a pointer Variable (nickname) — See http://bigblog.tanbin.com/2011/12/methods-are-fields-function-pointer.html
pointer comparison —- When you compare 2 pointers, you compare the addresses represented by 2 pointer variables. Apart from the 2 pointee objects A and B, there may not be two 32bit pointer Objects in memory whose 32 bits hold A’s or B’s addresses.
smart pointer —- When you pass a raw pointer to a smart pointer, you pass an Address, not necessarily a pointer Object or pointer Variable. A smart pointer is always an Object, never a pure Address.
wild pointer —- is a pointer Address, but a dangerous address. Object at the address is now bulldozed/reclaimed. SomeLibrary.getResource() may return an Address which becomes wild before you use it. If you don’t give a nick name to that returned value, it remains a wild pointer Address.
** now I feel even a stack object can be bulldozed, creating a wild pointer. getResource() may mistakenly return a pointer to an auto variable i.e. stack object
pointer argument or returning a pointer —– I think what’s passed is an address. I call it pbclone — the address is cloned just like an int value of 9713.
Most of the time we aren’t sure if a nickname refers to a 32-bit pointer object or pure information. The prime example of a 32-bit pointer object is a pointer field in a struct.