Difference between pointer declaration and indirection - c++

I'm reading a book and I have doubts about what each of these syntax does. The first three lines I can understand but the following do not. Thank you very much if you help me, Julieta
int m; //m is int variable
int *p; //Pointer p pointing to an integer value
p=&m //The memory address of the variable m is assigned to p
float *longitud;
longitud=&cable1;
*longitud=40.5;

The concepts of value, pointer, and reference often trip people up, especially as they are often taught to look at them in terms of implementation and not in terms of the language.
A value is a thing that exists and has meaning. It always has a type (a constraint on its meaning) like int, float, char, and vector<string>.
An object is a value that exists somewhere in memory. (And not, say, mangled into a machine instruction code or produced on-the-fly in some way. That is, I could take out my memory chip and stick my finger on it, were my fingers nimble enough.)
A reference is an alias — a name for an object. The name is convenient for us as programmers. How the compiler maintains that name does not really matter. All that matters (language perspective!) is that if you have a name, you have direct access to an object.
To put that into perspective, whenever you name an object, you obtain a direct reference to that object. You can manipulate that object directly using its name.
A pointer is a value. Its type is a location in the computer’s memory of some object. With this location, I can gain access to the object’s value. In other words, I can use a pointer to gain a direct reference to an object.
Vocabulary + time = fickle understandings and encourage people to ask useless things2. Let’s clean our minds up a little.
First, a pointer is not a reference, it is an indirect reference. In order to get an actual, or direct, reference to a pointed-to object, we “dereference” the pointer. In other words, we perform a magic that transforms a pointer value to obtain a reference to an object.
The mechanics of how a pointer works are typically framed in terms of how the underlying hardware does something like “follows a pointer to a value”. We draw pictures with arrows and everything. We seem to forget to ask how this magic works. No one asks how variable names work either, but it is the exact same kind of magic. We simply trust when told “the compiler takes care of it”.
What is missed is the distinction between a (direct) reference (an alias or name for an object) and an indirect reference (a pointer or other thing that can be used to obtain a reference to an object).
Before C++ the difference between direct and indirect references really only made sense in the context of a pointer, and it was easy to call a pointer “a reference” instead of the full phrase “an indirect reference”, and so the vocabulary words mixed around in our heads, and we began to misunderstand the actual concepts involved.
Enter C++, stage left. We now have things called “references” in addition to pointers. In terms of the language, they are true aliases for other objects1.
To put it to example:
int x = 7; // "x" is a reference to the integer object with value 7
int& y = x; // "y" is a reference to the same integer object as "x".
int* p = // "p" is a pointer object whose value is an
// indirect reference to some integer object:
&x; // The & operator obtains an indirect reference (or pointer value) to "x"
And here is the last point. There are more than one meaning for "&"!
When attached to a type, it means that the type is a direct reference to some object
When attached to an object, it means that an indirect reference to that object is obtained
1 In C++, the abstraction leaks, because the lifetime of an object is bound only to the original reference. But that’s neither here nor there. There are other topics that deal with that here at SO.
2 So, to answer everyone’s favorite question: is a reference a pointer or not? The answer is, it doesn’t matter. (Unless you are writing a compiler.) You are asking implementation details about magic used to maintain a language-level concept. So sometimes it may be an actual pointer, sometimes it may simply be another entry in the compiler’s local symbol table, and it may even be something else if the compiler writer thinks it useful and appropriate.
3Language gets to be fuzzy. I had previously said "p" is a pointer. Technically, it is an object whose value is a pointer type. We can usually get away by just saying what type of thing an object is, though, and be well-understood. It is only when we are splitting hairs (in context) that the vocabulary needs more care, as it does here.

longitude is a pointer to a float variable
longitud=&cable1 assigns the address of cable1 (presumably a float?) to longitud, which now references cable1.
*longitud=40.5 dereferences longitude and assign it value 40.5. Because longitud references cable1, this assigns the value to cable1. That is *longitud and cable1 are the same thing.
None of this really relates to the question title "Difference between pointer declaration and indirection" - indirection is a general computing concept, and pointers are the means by which indirection is effected in C and C++.

Suppose you add one more (different) line in each section:
int m; // m is int variable
int *p; // pointer p is pointing to an integer value
p = &m; // the memory address of m is assigned to p
*p = 42; // ADDED: assign 42 to m, where p points to
float cable1; // ADDED: the variable where longitud points
float *longitud; // pointer longitud is pointing to a float value
longitud = &cable1; // the memory address of cable1 is assigned to longitud
*longitud = 40.5f; // assign 40.5 to cable1, where longitud points to
This completes the similar examples, which use different variable types.

After executing the lines
float cable1; // ADDED: the variable where longitud points
float *longitud; // pointer longitud is pointing to a float value
longitud = &cable1; // the memory address of cable1 is assigned to longitud
the following conditions are true:
longitude == &cable1
*longitude == cable1
IOW, the expression *longitud is equivalent to the expression cable1. So when you write
*longitud = 40.5f;
this is equivalent to writing
cable1 = 40.5f;
The * operator dereferences the longitud pointer, such that the expression *longitud evaluates to the same thing as cable1.

Cable1 needs to have a place memory before longitud can point to it.
The first 3 lines do this:
Set aside memory for an int.
Create an int pointer.
Get the int pointer to point at the int's memory address. Pointer references int.
The second 3 lines do this:
Create a float pointer.
Get the float pointer to point to a nonexistent address.
Try to assign a float value to that address.
If on line 4 you wrote:
float cable1;
You would have set aside memory and everything would work fine.
On the topic, you mean pointer declaration and dereferencing. I can give a short set of examples, though it mostly takes reading and practice to learn. Try these out and get a feel.
float f = 22.2f; //sets aside memory for a float with the name "f", stores 22.2
float *pf; //declares a float pointer.
pf = &f; //sets pf to point to f's memory address. pf references p.
printf("%f", *pf); //prints the value at the referenced address (22.2)
printf("%x", pf); //prints the memory address of the pointer itself
*pf = 33.3f; //changes the value at f's address to 33.3 (from 22.2)
f = 44.4f; //changes the value at f's address to 44.4 (from 33.3)
float *pf2;
*pf2 = 33.3 //BAD. pf2 is not assigned to an address, no value to change.
*pf2 = f; //BAD. pf2 has no memory address to copy the value to.
*pf2 = pf; //BAD. several reasons.
pf2 = pf; //pf2 now points to f's address, too.
pf2 = &f; //redundant. Same as the last line.
*pf2 = 55.5 //f has changed to 55.5. both pf2 and pf point to it.
Just think of the * as standing for "pointer" when you declare. When you use * later, it means "dereference." Dereferencing a pointer means you want to look at/use/change the referenced value. Later on, you'll learn that pointers can point to other pointers. So the value of a (char **) type is type (char *), rather than type (char).
If you don't have a book, I recommend C Programming - A Modern Approach 2nd Edition. It's a little dated but an excellent way to learn the fundamentals.

Related

Implicit conversions and pointers?

Why does an implicit conversion not happen when making a float pointer point to an integer, such as when you assign a float variable an integer value?
I think it's easy to reason about it via allegory.
Think of a pointer as slip of paper with the address of a house written on it. The type of the data is the name of the person who resides in said house.
Now, casting a pointer is like taking that slip of paper, keeping the address the same (for the most part), but changing the name of the person who supposedly lives in the house.
Just because we changed the name on the paper from Alice to Bob, doesn't mean Alice magically becomes Bob. The paper doesn't influence the house.
That's why using such a pointer has undefined behavior. The code think it's addressing a Bob, when in fact it's Alice.
Because a pointer, well, it needs to point someplace. Because that's what a pointer is. When you have an
int *p;
And you dereference it, like, for example:
foo(*p);
You expect to dereference the pointer and end up with an int.
Now, if you start with a float:
float *q;
And let's say, for the sake of argument, you can do this:
int *p=q;
Then where exactly do you expect this pointer to point to, now? It can't point to wherever q is pointing to. Because the only thing over there is a float.
So, you have to do it yourself, manually:
int n= (int)*q;
int *p= &n;
And, of course, you have to make sure that n remains in scope as long as the p pointer gets dereferenced. And, if *q is changed to a different value, it won't affect what p is pointing to. But those would be different questions...

Can a pointer point to a value and the pointer value point to the address?

Normal pointer usage as I have been reading in a book is the following:
int *pointer;
int number = 5;
pointer = &number;
Then *pointer has a value of 5.
But does this work the other way around? I mean:
int *pointer;
int number = 5;
*pointer = &number;
Here does pointer contain the value 5 and *pointer holds the address of number?
Thanks.
In
int *pointer;
int number = 5;
*pointer = &number;
you never assign a valid address to pointer, so dereferencing that pointer (as is done by the expression *pointer) is not valid.
Analogy from the department of far-fetched analogies:
You use pointers many times every day without even thinking about it.
A pointer is an indirection - it tells you where something is, or how it can be reached, but not what that thing is.
(In a typed language, you can know what kind of thing it is, but that's another matter.)
Consider, for example, telephone numbers.
These tell you how to reach the person that the phone number belongs to.
Over time, that person may change - perhaps somebody didn't pay their bills and the number was reassigned - but as long as the number is valid, you can use it to reach a person.
Using this analogy, we can define the following operations:
&person gives you a person's phone number, and
*number gives you the person that the number belongs to.
Some rules:
There are only two types in this language - persons and phone numbers.
Only persons can have phone numbers; &number is an error, as is *person.
An unspecified phone number reaches the General Manager of Customer Services at Acme, Inc.
Now, your first example would translate to
PhoneNumber n;
Person Bob;
n = &Bob;
which makes sense; n now holds Bob's phone number.
Your second example would translate to
PhoneNumber n;
Person Bob;
*n = &Bob;
which would say "replace the General Manager of Acme Inc's Customer Services with Bob's phone number", which makes no sense at all.
And your final question,
Here does pointer contain the value 5 and *pointer holds the address of number?
would translate to
Is this phone number the same thing as Bob, and if you call it, will Bob's phone number answer?
which I am sure you can see is a rather strange question.
Your second case will not compile, because the assignment *pointer = &number involves incompatible types (int on the left, a pointer to int on the right) which makes the assignment invalid.
If you somehow coerce the assignment into compiling, then pointer is not initialised. Accessing its value, let alone dereferencing it (e.g. evaluating *pointer or assigning to it as in *pointer = number or *pointer = 5) gives undefined behaviour. Anything can happen then .... depending on circumstances, a common result of undefined behaviour is an abnormal program termination.
*pointer = &number; is not valid C.
*pointer is of type int and &number is of type int*. This isn't a valid form of assignment and will not compile on a standard C compiler.
You can store numbers inside pointer variables, but then you must use an explicit cast to force a type conversion. Some compilers allow it without an explicit cast, but note that doing so is a non-standard extension.
And of course, note that you haven't set pointer to point at an allocated memory address, so you can't store anything inside where it points.
If you do an explicit cast such as
pointer = &something;
*pointer = (int)&number;
then it is allowed in C, but if you try to de-reference that pointer, the behavior is implementation-defined. It could possibly also be undefined behavior in case of misalignment etc. See C11 6.3.2.3:
An integer may be converted to any pointer type. Except as previously
specified, the result is implementation-defined, might not be
correctly aligned, might not point to an entity of the referenced
type, and might be a trap representation.
When you create a pointer variable, initially it will have garbage value (let say 300 address location). Hence when you dereference pointer(*300), it would give another garbage value(value at 300 address location) or error (strictly speaking anything may happen depending on your computer).
In the third step, &number:- which is also another number and your are trying to assign a number to *pointer(may be another number) which not possible. (It is like this:- 5=6). Hence it will be an error.
For you to write an assignment x = y, both x and y must be, or be implicitly convertible to, the same type (or x must have a user-defined assignment operator taking an argument matching the type of y, or ... OK, there are a few possibilities, but you get the idea).
Now, let's look at the statement
*pointer = &number;
Here, *pointer has type int& - you followed the pointer to get a (reference to) the integer stored at that location. Let's ignore, for now, the fact that your pointer was uninitialized and following it results in undefined behaviour.
The right hand side, &number, is taking a pointer to an integer variable, so the type is int*.
So, the expression doesn't make sense at all, just in terms of the type system: there is no way to assign int* to int&. It doesn't mean anything.
Let's relate it back to the English language of your question
Here does pointer contain the value 5 and *pointer holds the address of number?
That translates directly to the type system, and hence also doesn't mean anything. Again, we can break it down
does pointer contain the value 5
a pointer contains a location. The only time it would make sense to talk about a pointer having a literal value (other than nullptr) would be on a platform where there were well-known addresses - this is rare, and '5' is very unlikely to be a well-formed address anyway
*pointer holds the address
well, there is a case where *pointer could hold an address - it's where *pointer is itself is a pointer, meaning the variable pointer is a pointer-to-pointer such as int **. That isn't the case here: we know the type of *pointer in your code, and it is int&, not int*.

How reference share the memory address

i was reading what is difference b/w pointer variable and reference variable in c++ here's. i got a point from that whereas a reference shares the same memory address but also takes up some space on the stack..
what does it mean that it share the same address space.please clear the how reference has been implemented in c++.
That's a somewhat confusingly-worded answer. But it means something rather simple. The part about taking up stack space just means a reference actually takes up memory. Namely, it takes up the same amount of memory that a pointer does (and in every C++ implementation [that I'm aware of] it's implemented by using an actual pointer).
The part about "share the same memory address" really means that a reference is not an independently-addressable value. If you have a pointer to something, you can take the address of that pointer and end up with a pointer to a pointer to something. But if you have a reference to something, you cannot take the address of that reference. Attempting to do so actually takes the address of the thing being referred to. That is what he means by "shares the same memory address".
Roghly speaking, a reference variable is like a pointer variable that does not look like a pointer (i.e. no pointer syntax for accessing the content). That does not have to do anything with Stack or Heap.
int i = 5; // integer on the Stack
int * j = new int (5); // integer on the Heap (accessible through pointer, naturally)
int & iref = i; // reference to integer on the Stack
int & jref = *j; // reference to integer on the Heap
int * ipointer = & i; // pointer to integer on the Stack
int * jpointer = j; // pointer to integer on the Heap

Intuitively explaining pointers and their significance?

I'm having a hard time understanding pointers, particularly function pointers, and I was hoping someone could give me a rundown of exactly what they are and how they should be used in a program. Code blocks in C++ would be especially appreciated.
Thank you.
The concept of indirection is important to understand.
Here we are passing by value (note that a local copy is created and operated on, not the original version) via increment(x):
And here, by pointer (memory address) via increment(&x):
Note that references work similarly to pointers except that the syntax is similar to value copies (obj.member) and that pointers can point to 0 ("null" pointer) whereas references must be pointing to non-zero memory addresses.
Function pointers, on the other hand, let you dynamically change the behaviour of code at runtime by conveniently passing around and dealing withh functions in the same way you would pass around variables. Functors are often preferred (especially by the STL) since their syntax is cleaner and they let you associate local state with a function instance (read up about callbacks and closures, both are useful computer science concepts). For simple function pointers/callbacks, lambdas are often used (new in C++11) due to their compact and in-place syntax.
The pointer points to the point, is an integer value that has the address of that point.
Pointers can point to other pointers. Then you can get the values more-indirect way.
Reference operator (&):
You may equate a pointer to a reference of a variable or a pointer.
Dereference operator (*):
You may get the value of cell pointed by the pointer.
Arrays are decayed into a pointer when passed to a function by not a reference.
Function pointers are not inlined and makes program more functional. Callback is an example to this.
As an analogy, think of the memory in the computer as an Excel sheet. The equivalent of assigning a value to a variable in a C/C++ program would be to write something into a cell on the Excel sheet. Reading from a variable would be like looking at a cell's content.
Now, if you have a cell (say C3) whose content is "B8" you can interpret that content as a reference to another cell. If you treat the cell C3 in that manner, C3 becomes like a pointer. (In Excel, you can actually achieve this behavior by entering =B8 into C3).
In such a scenario, you basically state that the cell whose value you're interested in is referenced in C3. In C++, this could be something like:
int B8 = 42;
int* C3 = &B8;
You now have two variables that occuppy memory. Now, if you want to know what C3 points to, you'll use
int my_value = *C3;
As for function pointers: these are variables like ordinary pointers but the address (cell) they point to is not just a value but rather a function you can call.
Here you can find some example uses of Function pointer:
http://www.cprogramming.com/tutorial/function-pointers.html
In order to understand pointers one needs to understand a bit about hardware and memory layout.
Computer memory can be seen as a cupboard with drawers. A pointer can point to an arbitrary drawer, when you "dereference" the pointer you are looking inside the drawer, i.e. the value stored in the "drawer":
e.g. ten numbers stored after one another
short a[] = {9,2,3,4,5,6,7,8,1,-1] ;
in memory the values that consist the array 'a' are stored sequentially
+---+---+---+---+---+---+---+---+---+---+
a->| 9 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1 | -1|
+---+---+---+---+---+---+---+---+---+---+
the 'a' array above is a pointer and is the start address where the
values are stored in memory.
short* ptr = 0; // a pointer not pointing to anything (NULL)
ptr = a + 5; // the pointer is now pointing to the 6th value in the array
// the + 5 is an offset on the starting address of a and since the type of
// a is short int array the compiler calculates the correct byte offset based
// on that type. in the above example 5 is 5 short ints since ptr is of type
// short*
*ptr has the value 6 i.e. we are looking at what the ptr is pointing to.
The size of each "drawer" is determined of the data type that is stored
In the above example 10 short ints are stored, every short int occupies 2 bytes
so the whole array occupies 20 bytes of memory (sizeof(a))
Variables store values.
Pointers store values too. The only difference is that they are memory addresses. They are still numbers.
Nothing complicated here.
You could store all pointers in int or long variables:
int p = 43567854;
char *p1 = (char *) p;
But advantage of storing them in pointer variables is that you can describe what type of variable is saved at the address the pointer points to.
What gets complicated about pointers is the cryptic syntax you have to use with them. Syntax is cryptic so that it's short to type.
Like:
&p = return address of variable
*p = return the value of first member of array that is stored at the address
By using the two rules above we can write this cryptic code:
&(*++t)
Which translated into human language gets quite long:
Increase value of t by 1. this now points to second member of array of values pointer points to. then get value of second member (*) and then get address of this value. if we print this pointer it will print whole string except the first character.
You should make a "pointers syntax cheat sheet.txt" and you are good.
And have open "Pointers tests" projects to test everythng that is unclear to you.
Pointers are similar to regular expressions in a way.

About pointer and reference syntax

Embarrassing though it may be I know I am not the only one with this problem.
I have been using C/C++ on and off for many years. I never had a problem grasping the concepts of addresses, pointers, pointers to pointers, and references.
I do constantly find myself tripping over expressing them in C syntax, however. Not the basics like declarations or dereferencing, but more often things like getting the address of a pointer-to-pointer, or pointer to reference, etc. Essentially anything that goes a level or two of indirection beyond the norm. Typically I fumble with various semi-logical combinations of operators until I trip upon the correct one.
Clearly somewhere along the line I missed a rule or two that simplifies and makes it all fall into place. So I guess my question is: do you know of a site or reference that covers this matter with clarity and in some depth?
I don't know of any website but I'll try to explain it in very simple terms. There are only three things you need to understand:
variable will contain the contents of the variable. This means that if the variable is a pointer it will contain the memory address it points to.
*variable (only valid for pointers) will contain the contents of the variable pointed to. If the variable it points to is another pointer, ptr2, then *variable and ptr2 will be the same thing; **variable and *ptr2 are the same thing as well.
&variable will contain the memory address of the variable. If it's a pointer, it will be the memory address of the pointer itself and NOT the variable pointed to or the memory address of the variable pointed to.
Now, let's see a complex example:
void **list = (void **)*(void **)info.List;
list is a pointer to a pointer. Now let's examine the right part of the assignment starting from the end: (void **)info.List. This is also a pointer to a pointer.
Then, you see the *: *(void **)info.List. This means that this is the value the pointer info.List points to.
Now, the whole thing: (void **)*(void **)info.List. This is the value the pointer info.List points to casted to (void **).
I found the right-left-right rule to be useful. It tells you how to read a declaration so that you get all the pointers and references in order. For example:
int *foo();
Using the right-left-right rule, you can translate this to English as "foo is a function that returns a pointer to an integer".
int *(*foo)(); // "foo is a pointer to a function returning a pointer to an int"
int (*foo[])(); // "foo is an array of pointers to functions returning ints"
Most explanations of the right-left-right rule are written for C rather than C++, so they tend to leave out references. They work just like pointers in this context.
int &foo; // "foo is a reference to an integer"
Typedefs can be your friend when things get confusing. Here's an example:
typedef const char * literal_string_pointer;
typedef literal_string_pointer * pointer_to_literal_string_pointer;
void GetPointerToString(pointer_to_literal_string_pointer out_param)
{
*out_param = "hi there";
}
All you need to know is that getting the address of an object returns a pointer to that object, and dereferencing an object takes a pointer and turns it into to object that it's pointing to.
T x;
A a = &x; // A is T*
B b = *a; // B is T
C c = &a; // C is T**
D d = *c; // D is T*
Essentially, the & operator takes a T and gives you a T* and the * operator takes a T* and gives you a T, and that applies to higher levels of abstraction equally e.g.
using & on a T* will give you a T**.
Another way of thinking about it is that the & operator adds a * to the type and the * takes one away, which leads to things like &&*&**i == i.
I'm not sure exactly what you're looking for, but I find it helpful to remember the operator precedence and associativity rules. That said, if you're ever confused, you might as well throw in some more parens to disambiguate, even if it's just for your benefit and not the compiler's.
edit: I think I might understand your question a little better now. I like to think of a chain of pointers like a stack with the value at the bottom. The dereferencing operator (*) pops you down the stack, where you find the value itself at the end. The reference operator (&) lets you push another level of indirection onto the stack. Note that it's always legal to move another step away, but attempting to dereference the value is analogous to popping an empty stack.