In this example, what is x? Is it a reference?
int x = 5; //What is x?
int &y = x; //This is an alias for x
int *z = &x; //This is a pointer to x
No x is int variable. y is reference to int (x) and z is pointer to int (x).
You are getting confused.
x is an int variable. It is a concrete object of type int.
y is a reference. It is basically a pointer that's already deferenced for you. You can treat it as if it was x.
z is a pointer to x. It holds the memory address of x, so you can access it if needed. It needs to be deferenced.
You can understand the "non-reference variable" as something from which a reference can be taken. Every variable "consists of" a "reference", which is a language interface for it, and the internal representation, which is a piece of memory that holds its value.
If you create a "reference variable" and initialize it with some normal variable, you will create a new "reference", that is, another "language interface" (a separate name) that is pinned into the same internal representation as the source variable. Note that it's bound to the internal representation of the variable, not the variable itself.
The pointer simpy points to the representation itself. The pointed type is a potential type of the "reference" (that is, the language interface to the variable), if you do "pointer dereference" (use *z expression).
The actual type of an expression of the variable 'x' is 'int&'. If you pass it to a function or assign to another variable (in C++ they are both understood as "function call"), there will be a conversion from int& to int. Note, however, that if you pass it to a function where a template-parametrized type is used on that position, and it will be specified as "T x" (not "T& x"), then T will be picked up as 'int' (not int&), no matter if you passed an immediate int value or a variable of type int.
X is an integer variable.
int &y =x; // is treated by compiler as int *const y = &x
So reference operator is used as name aliasing for variables and reduces the complexity of dereferencing the value by developer.
Related
I've been looking a bit into pointers. I've found the small differences in declaring pointers like int* x, or int *x. However, I've always thought of *x as the actual value as the pointed memory. So when I read int *x = &a, I read it as "assign value at pointed address of x to &a", which is obviously not what is happening. The variable a mem address is being assigned to pointer x. How should I be reading it? Whenever I see *x, I just think it's the literal value at pointed address by x. Is it because in any pointer declaration, whatever value it is first initialized with it is always treated as the assigned mem address to point at?
When you see a declaration such as:
int *x = &a;
you should interpret it as:
int *x;
x = &a;
The declaration syntax is visually confusing. It is not intended that int *x = &a; have an appearance of *x = &a;. What happened historically is that we had simple assignments, like x = &a;, and we also had declarations. In the C style of declarations, we show how we want to use a variable:
int x; // I want x to be an int. Therefore, x is an int.
int *x; // I want *x to be an int. Therefore, x is a pointer to an int.
int x(); // I want x() to be an int. Therefore, x is a function that returns an int.
int x[3]; // I want x[i] to be an int. Therefore, x is an array of int.
int *x[3]; // I want *x[i] to be an int. Therefore, x is an array of pointers to int.
Next, we want to combine both the declaration and the assignment—partly for brevity in the source code, and partly to emphasize that this is the initial value for an object, the value it has the moment it is defined. To do this, the declaration and the assignment were jammed together, resulting in:
int *x = &a;
This causes *x = &a to appear in the statement, but it is not assigning &a to *x. It is initializing x, not *x. The *x appears only because it is part of the declaration. I suppose this could have been made less confusing by separating the assignment part and the declaration part but keeping them in the same statement, perhaps something like:
int *x : x = &a;
But, regardless of what could have been done, int *x = &a; is what we have.
I've found the small differences in declaring pointers like int* x, or int *x
There is no semantic difference. Both are same as well as int*x and int * x.
How should I be reading [int *x = &a]?
"x is initialised to point to a". Or alternatively, "... to store the address of a".
Furthermore, you should also read that x was declared to have the type int* i.e. pointer to int. Depending on context, different aspects of a declaration may be more important than others. For example, if we already know that a is an integer, it might be obvious from the context that a variable pointing to it is a pointer to an integer unless stated otherwise.
"Assign the address of 'a' to 'x'".
If you make an integer as such called "sum":
#include <iostream>
int main(){
int sum = 57;
std::cout << &sum << std::endl; //Prints the address
std::cout << *(&sum) << std::endl; //Prints 57
std::cout << sum << std::endl; //Prints 57
return 0;
}
You will see that the ampersand is asking for the address of the variable. Pointers are just another variable, they contain addresses instead of what we would understand as "useful values".
As far as I'm aware, it's just a question of style("int *x" vs "int* x"). When you don't declare a variable, but you invoke it, then the asterisk acts as a dereference, i.e. it steps into the address contained within the variable to go back to whatever the pointer points to.
Depending on the context, *x is pronounced very differently.
int *x;
This is pronounced: declare x to be a pointer to an int.
y = *x;
This is pronounced: take the value that x points to, and copy it to y.
Having these two entirely different pronunciations may seem strange at first. But there's a deeper meaning to it. The inventors of the C programming language wanted to allow an alternative pronunciation for the above declaration.
The alternative pronunciation for int *x; is: declare a variable such that the type of the expression *x is int.
This alternative pronunciation rule also works for very complicated types, like functions returning functions of functions, therefore it is worth learning.
I've found the small differences in declaring pointers like int* x, or int *x.
These two are the exact same, the space does not make a difference.
A pointer is just an integer that stores a memory address, like a door number which points to a house.
The ampersand in front of an existing variable is basically asking the variable what is your memory address. eg:
int var =8;
int* ptr = &var;
Here I am taking the memory address of the variable var and assigning it to a new variable called ptr.
Now I'm not 100% sure what your question is but hopefully this may help a little.
EDIT:
I would highly recommend watching this video series, It's super long but the first couple of videos explain pointers, references and operators very well, take notes if you can. The Cherno C++ Tutorial
I'm not sure if I can ask basic questions here, but I am starting to learn C++ and do not understand one little thing in pointers syntax.
Here is the sample of my code:
using namespace std;
int randomname(int *x);
int main(){
int a = 1;
int *ab;
ab = &a;
randomname(&a);
}
int randomname(int *x){
*x = 9001;
}
My question is about the * symbol. Why in the main function on line ab = &a; I don't need the *, but on line *x = 9001; I need it? I think syntax should be same in both functions, but it isn't. Can someone please explain why?
The meaning of both the asterisk * and the ampersand & changes depending on the context. Their meanings in expressions and in declarations are different:
When * is used in a declaration, it designates a pointer
When & is used in a declaration, it designates a reference
When * is used in an expression, it performs a pointer dereference of its operand
When & is used in an expression, it obtains a pointer of its operand
Once you understand these distinctions, you can tell that
Line int *ab is a declaration. Asterisk designates ab as a pointer.
Line ab = &a; has an expression. & takes a's pointer, and assigns it to ab, which has a pointer type specified at the time of its declaration (above).
Line *x = 9001 is also an expression, making the asterisk a dereference operator. You use the asterisk to tell the compiler that the target of the assignment is whatever is pointed to by x, not x itself.
You need the asterisk when you are declaring a pointer, or when you are dereferencing the pointer. The syntax actually is the same in both functions, but what is being assigned in each of the assignment statements is different.
An int is a value. An int variable is stored in a storage location. A pointer to an int is also a value, but its value refers to a storage location. When you are performing an assignment with a pointer, you could assign the value of the pointer itself (the address of the storage location it refers to), or you could assign a value to the storage location it refers to.
In the case of int *x in the formal parameters of the function, or in the declaration int *ab that defines the ab variable, you need the asterisk because you are declaring a variable or a parameter to be of type "pointer to int".
In the assignment ab = &a you do not need the asterisk because you are assigning the address of variable a to the pointer ab -- you are assigning the value of the pointer itself, not what it points to.
In the assignment *x = 9001, you need the asterisk to get the storage location that the pointer refers to. This is called "dereferencing" the pointer. You are not assigning a value to the pointer itself, but instead you are assigning a value to the storage location to which the pointer refers, which is the storage allocated for variable a in function main.
This article by Eric Lippert may be of considerable help to you:
What are the fundamental rules of pointers?
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
c++ * vs & in function declaration
I know that this probably seems like an incredibly elementary question to many of you, but I have genuinely had an impossible time finding a good, thorough explanation, despite all my best Googling. I'm certain that the answer is out there, and so my search terms must be terrible.
In C++, a variety of symbols and combinations thereof are used to mark parameters (as well as arguments to those parameters). What, exactly, are their meanings?
Ex: What is the difference between void func(int *var) and void func(int **var)? What about int &var?
The same question stands for return types, as well as arguments. What does int& func(int var) mean, as compared to int* func(int var)? And in arguments, how does y = func(*x) differ from y = func(&x)?
I am more than happy to read enormous volumes on the subject if only you could point me in the right direction. Also, I'm extremely familiar with general programming concepts: OO, generics/templates, etc., just not the notation used in C/C++.
EDIT: It seems I may have given the impression that I do not know what pointers are. I wonder how that could be :)
So for clarification: I understand perfectly how pointers work. What I am not grasping, and am weirdly unable to find answers to, is the meaning of, for example 'void func(int &var)'. In the case of an assignment statement, the '&' operator would be on the right hand side, as in 'int* x = &y;', but in the above, the '&' operator is effectively on the left hand side. In other words, it is operating on the l-value, rather than the r-value. This clearly cannot have the same meaning.
I hope that I'm making more sense now?
To understand this you'll first need to understand pointers and references. I'll simply explain the type declaration syntax you're asking about assuming you already know what pointers and references are.
In C, it is said that 'declaration follows use.' That means the syntax for declaring a variable mimics using the variable: generally in a declaration you'll have a base type like int or float followed something that looks like an expression. For example in int *y the base type is int and the expression look-alike is *y. Thereafter that expression evaluates to a value with the given base type.
So int *y means that later an expression *y is an int. That implies that y must be a pointer to an int. The same holds true for function parameters, and in fact for whole function declarations:
int *foo(int **bar);
In the above int **bar says **bar is an int, implying *bar is a pointer to an int, and bar is a pointer to a pointer to an int. It also declares that *foo(arg) will be an int (given arg of the appropriate type), implying that foo(arg) results in a pointer to an int.¹ So the whole function declaration reads "foo is a function taking a pointer to a pointer to an int, and returning a pointer to an int."
C++ adds the concept of references, and messes C style declarations up a little bit in the process. Because taking the address of a variable using the address-of operator & must result in a pointer, C doesn't have any use for & in declarations; int &x would mean &x is an int, implying that x is some type where taking the address of that type results in an int.² So because this syntax is unused, C++ appropriates it for a completely different purpose.
In C++ int &x means that x is a reference to an int. Using the variable does not involve any operator to 'dereference' the reference, so it doesn't matter that the reference declarator symbol clashes with the address-of operator. The same symbol means completely different things in the two contexts, and there is never a need to use one meaning in the context where the other is allowed.
So char &foo(int &a) declares a function taking a reference to an int and returning a reference to a char. func(&x) is an expression taking the address of x and passing it to func.
1. In fact in the original C syntax for declaring functions 'declarations follow use' was even more strictly followed. For example you'd declare a function as int foo(a,b) and the types of parameters were declared elsewhere, so that the declaration would look exactly like a use, without the extra typenames.
2. Of course int *&x; could make sense in that *&x could be an int, but C doesn't actually do that.
What you're asking about are called pointers (*), and reference to (&), which I think is best explained here.
The symbols & and * are used to denote a reference and pointer type, respectively.
int means simply the type 'int',
int* means 'pointer to int',
int& means 'reference to int',
A pointer is a variable which is used to store the address of a variable.
A reference has the syntax of its base type, but the semantics of a pointer to that type. This means you don't need to dereference it in order to change the value.
To take an example, the following code blocks two are semantically equivalent:
int* a = &value;
*a = 0;
And:
int& a = value;
a = 0;
The main reasons to use pointers or references as an argument type is to avoid copying of objects and to be able to change the value of a passed argument. Both of these work because, when you pass by reference, only the address is copied, giving you access to the same memory location as was "passed" to the function.
In contrast, if a reference or pointer type is not used, a full copy of the argument will be made, and it is this copy which is available inside the function.
The symbols * and & have three meanings each in C++:
When applied to an expression, they mean "dereference" and "address-of" respectively, as you know.
When part of a type, they mean "pointer" and "reference", respectively.
Since C++ doesn't care about arbitrary spacing, the declaration int *ptr is exactly the same as the declaration int* ptr, in which you can now more clearly see that this is an object called ptr of type int*.1
When used between two expressions, they mean "multiply" and "bitwise AND", respectively.
1 - though, frustratingly, this isn't actually how the internal grammar reads it, thanks to the nasty legacy of C's type system. So avoid single-line multi-declarations involving pointers unless you want a surprise.
Ex: What is the difference between 'void func(int *var)' and 'void
func(int **var)'? What about 'int &var'?
The same question stands for return types, as well as arguments. What
does 'int& func(int var)' mean, as compared to 'int* func(int var)'?
And in arguments, how does 'y = func(*x)' differ from 'y = func(&x)'?
(1)
<return type> <function name> <parameters>
void func (int *var)
<parameter> here int *var is a pointer to integer, ie it can point to
an array or any buffer that should be handled with integer pointer
arithmetic. In simple terms , var holds the address of the respective
**actual parameter.**
eg: int arr[10];
func(arr);
int a = 33;
func(&a);
Here, &a means we are explicitly passing address of the the variable 'a'.
(2)
int m = 0;
int &var = m;
Here var means reference, ie it another alias name for variable 'm' ,
so any change 'var' makes will change the contents of variable 'm'.
var = 2; /* will change the actual contents of 'm' */
This simple example will not make sense , unless you understand the context.
Reference are usually use to pass parameter to function, so that changes made by
the function to the passed variable is visible at the caller.
int swap(int &m, int &n) {
tmp = m;
m = n;
n = tmp;
}
void main( void ) {
int x = 1, y = 2;
swap(x, y);
/* x = 2, y =1 */
}
(3)
'int& func(int var)' mean, as compared to 'int* func(int var)'?
int& func(int var) means the function returns a reference;
int* func(int var) means the function returns a pointer / address;
Both of the them has its context;
int& setNext() {
return next;
}
setNext() = previous;
where as
int* setNext() {
return &next;
}
int *inptr;
inptr = setNext();
*inptr = previous;
In the previous two lines,
int *inptr <- integer pointer declaration;
*inptr <- means we are accessing contents of the address pointed by inptr;
ie we are actually referring to 'next' variable.
The actual use is context specific. It can't be generalized.
(4)
how does 'y = func(*x)' differ from 'y = func(&x)'?
y = func(&x) is already explained.
y = func(*x) , well i'm not sure if you actually meant *x.
int swap(int *m, int *n) {
tmp = *m;
*m = *n;
*n = tmp;
}
#include<iostream>
int & fun();
int main()
{
int p = fun();
std::cout << p;
return 0;
}
int & fun()
{
int a=10;
return a;
}
Why is this program not giving error at line no.6 as "invalid conversion from int* to int", as it happens in case we do like this?
int x = 9;
int a = &x;
int& is a type; it means "a reference to int."
&x is an expression; it means "take the address of x." The unary & operator is the address operator. It takes the address of its argument. If x is an int, then the type of &x is "a pointer to int" (that is, int*).
int& and int* are different types. References and pointers are the same in many respects; namely, they both refer to objects, but they are quite different in how they are used. For one thing, a reference implicitly refers to an object and no indirection is needed to get to the referenced object. Explicit indirection (using * or ->) is needed to get the object referenced by a pointer.
These two uses of the & are completely different. They aren't the only uses either: for example, there is also the binary & operator that performs the bitwise and operation.
Note also that your function fun is incorrect because you return a reference to a local variable. Once the function returns, a is destroyed and ceases to exist so you can never use the reference that is returned from the function. If you do use it, e.g. by assigning the result of fun() to p as you do, the behavior is undefined.
When returning a reference from a function you must be certain that the object to which the reference refers will exist after the function returns.
Why is this program not giving error at line no.5 as "invalid conversion from int* to int", as it happens in case we do like this?
That's because you are trying to return the variable by reference and not by address. However your code invokes Undefined Behaviour because returning a reference to a local variable and then using the result is UB.
Because in one case its a pointer and in the other a reference:
int a=&x means set a to the address of x - wrong
int &p=fun() means set p to a reference to an int - ok
Functions in C++ are not same as macros i.e. when you qrite int p = fun() it doesn't become int p = &a; (I guess that is what you are expecting from your question). What you are doing is returning a reference from the function f. You are no where taking address of any variable. BTW, the above code will invoke undfeined behavior as you are returning a reference to the local variable.
You're not returning an int *, you're retuning an int &. That is, you're returning a reference to an integer, not a pointer. That reference can decay into an int.
Those are two different things, although they both use the ampersand symbol. In your first example, you are returning a reference to an int, which is assignable to an int. In your second example, you are trying to assign the address of x (pointer) to an int, which is illegal.
I have a fairly good understanding of the dereferencing operator, the address of operator, and pointers in general.
I however get confused when I see stuff such as this:
int* returnA() {
int *j = &a;
return j;
}
int* returnB() {
return &b;
}
int& returnC() {
return c;
}
int& returnC2() {
int *d = &c;
return *d;
}
In returnA() I'm asking to return a pointer; just to clarify this works because j is a pointer?
In returnB() I'm asking to return a pointer; since a pointer points to an address, the reason why returnB() works is because I'm returning &b?
In returnC() I'm asking for an address of int to be returned. When I return c is the & operator automatically "appended" c?
In returnC2() I'm asking again for an address of int to be returned. Does *d work because pointers point to an address?
Assume a, b, c are initialized as integers as Global.
Can someone validate if I am correct with all four of my questions?
Although Peter answered your question, one thing that's clearly confusing you is the symbols * and &. The tough part about getting your head around these is that they both have two different meanings that have to do with indirection (even excluding the third meanings of * for multiplication and & for bitwise-and).
*, when used as part of a type
indicates that the type is a pointer:
int is a type, so int* is a
pointer-to-int type, and int** is a
pointer-to-pointer-to-int type.
& when used as part of a type indicates that the type is a reference. int is a type, so int& is a reference-to-int (there is no such thing as reference-to-reference). References and pointers are used for similar things, but they are quite different and not interchangable. A reference is best thought of as an alias, or alternate name, for an existing variable. If x is an int, then you can simply assign int& y = x to create a new name y for x. Afterwords, x and y can be used interchangeably to refer to the same integer. The two main implications of this are that references cannot be NULL (since there must be an original variable to reference), and that you don't need to use any special operator to get at the original value (because it's just an alternate name, not a pointer). References can also not be reassigned.
* when used as a unary operator performs an operation called dereference (which has nothing to do with reference types!). This operation is only meaningful on pointers. When you dereference a pointer, you get back what it points to. So, if p is a pointer-to-int, *p is the int being pointed to.
& when used as a unary operator performs an operation called address-of. That's pretty self-explanatory; if x is a variable, then &x is the address of x. The address of a variable can be assigned to a pointer to the type of that variable. So, if x is an int, then &x can be assigned to a pointer of type int*, and that pointer will point to x. E.g. if you assign int* p = &x, then *p can be used to retrieve the value of x.
So remember, the type suffix & is for references, and has nothing to do with the unary operatory &, which has to do with getting addresses for use with pointers. The two uses are completely unrelated. And * as a type suffix declares a pointer, while * as a unary operator performs an action on pointers.
In returnA() I'm asking to return a pointer; just to clarify this works because j is a pointer?
Yes, int *j = &a initializes j to point to a. Then you return the value of j, that is the address of a.
In returnB() I'm asking to return a pointer; since a pointer points to an address, the reason why returnB() works is because I'm returning &b?
Yes. Here the same thing happens as above, just in a single step. &b gives the address of b.
In returnC() I'm asking for an address of int to be returned. When I return c is the & operator automatically appended?
No, it is a reference to an int which is returned. A reference is not an address the same way as a pointer is - it is just an alternative name for a variable. Therefore you don't need to apply the & operator to get a reference of a variable.
In returnC2() I'm asking again for an address of int to be returned. Does *d work because pointers point to an address?
Again, it is a reference to an int which is returned. *d refers to the original variable c (whatever that may be), pointed to by c. And this can implicitly be turned into a reference, just as in returnC.
Pointers do not in general point to an address (although they can - e.g. int** is a pointer to pointer to int). Pointers are an address of something. When you declare the pointer like something*, that something is the thing your pointer points to. So in my above example, int** declares a pointer to an int*, which happens to be a pointer itself.
Tyler, that was very helpful explanation, I did some experiment using visual studio debugger to clarify this difference even further:-
int sample = 90;
int& alias = sample;
int* pointerToSample = &sample;
Name Address Type
&alias 0x0112fc1c {90} int *
&sample 0x0112fc1c {90} int *
pointerToSample 0x0112fc1c {90} int *
*pointerToSample 90 int
alias 90 int &
&pointerToSample 0x0112fc04 {0x0112fc1c {90}} int * *
Memory Layout
PointerToSample Sample/alias
_______________......____________________
0x0112fc1c | | 90 |
___________|___.....__|________|_______...
[0x0112fc04] ... [0x0112fc1c
In returnC() and returnC2() you are not asking to return the address.
Both these functions return references to objects.
A reference is not the address of anything it is an alternative name of something (this may mean the compiler may (or may not depending on situation) use an address to represent the object (alternatively it may also know to keep it in register)).
All you know that a reference points at a specific object.
While a reference itself is not an object just an alternative name.
All of your examples produce undefined run-time behavior. You are returning pointers or references to items that disappear after execution leaves the function.
Let me clarify:
int * returnA()
{
static int a; // The static keyword keeps the variable from disappearing.
int * j = 0; // Declare a pointer to an int and initialize to location 0.
j = &a; // j now points to a.
return j; // return the location of the static variable (evil).
}
In your function, the variable j is assigned to point to a's temporary location. Upon exit of your function the variable a disappears, but it's former location is returned via j. Since a no longer exists at the location pointed to by j, undefined behavior will happen with accessing *j.
Variables inside functions should not be modified via reference or pointer by other code. It can happen although it produces undefined behavior.
Being pedantic, the pointers returned should be declared as pointing to constant data. The references returned should be const:
const char * Hello()
{
static const char text[] = "Hello";
return text;
}
The above function returns a pointer to constant data. Other code can access (read) the static data but cannot be modified.
const unsigned int& Counter()
{
static unsigned int value = 0;
value = value + 1;
return value;
}
In the above function, the value is initialized to zero on the first entry. All next executions of this function cause value to be incremented by one. The function returns a reference to a constant value. This means that other functions can use the value (from afar) as if it was a variable (without having to dereference a pointer).
In my thinking, a pointer is used for an optional parameter or object. A reference is passed when the object must exist. Inside the function, a referenced parameter means that the value exists, however a pointer must be checked for null before dereferencing it. Also, with a reference, there is more guarantee that the target object is valid. A pointer could point to an invalid address (not null) and cause undefined behavior.
Semantically, references do act as addresses. However, syntactically, they are the compiler's job, not yours, and you can treat a reference as if it is the original object it points to, including binding other references to it and having them refer to the original object too. Say goodbye to pointer arithmetic in this case.
The downside of that is that you can't modify what they refer to - they are bound at construct time.