When should I use * and when &? [duplicate] - c++

This question already has answers here:
When to use references vs. pointers
(17 answers)
Closed 7 years ago.
I am learning some C++, and I came across pointers and addresses. However, in none of the materials, I could find a good explanation on when to use pointer, and when to use address. As I understand it is that when I use pointer, I POINT to address in memory, where some variable is stored. So for example:
int x = 5;
int k* = &x;
Which will mean that:
k represents x
When I change k, I also change value of x.
My question is as follows: when should I use pointer, and when should I use address? When I declare a function, should I use pointer, or address as a variable?

You have a typo there. It should be:
int x = 5;
int *k = &x;
It should be read as: k points to x. Or if you insist on the "represent" word: *k represents x.
The & operator takes any variable as argument and returns its address (pointer). The * gets a pointer (address) as argument and returns the value stored there. As such they are opposite operations: &*k is the same as k and likewise *&x is just like x. You can look at these expression this way:
x //an integer
k //pointer to integer
&x //pointer to x
*k //integer pointed to by k
*&x //integer pointed to by a pointer to x, that is x
&*k //pointer to the integer pointed to by k, that is k
Note that operator & can only be used on variables, as expressions in general do not have addresses, only variables do (well, and temporaries, but that is another matter). For example, this expression is invalid:
&(x + 1) //error!
The funniest thing with these operator is how a pointer is declared:
int *k;
You might think that it would be better written as int &k, but that's not how declarators are read in C++. Instead, that declaration should be read as:
int (*k);
that is, *k is an integer, so it results that k is a pointer to an integer.
Now, the declaration with initialization is weirder:
int *k = &x;
should actually be read as:
int (*k);
k = &x;
That is, you declare *k as being an integer, thus, k is a pointer-to-integer. And then you initialize k (the pointer) with the address of x.
Actually you can create pointers of any type, even pointers to pointers, pointers to pointers to pointers... but note that this syntax is illegal:
int x;
int **p = &&x; //error, &x is not a variable
but this is valid:
int x;
int *k = &x;
int **p = &k;

If a variable stores an address of a memory location, it is considered a pointer. So an int * for example stores the address of an int-variable. By using the dereference-operator *, you can access the memory location at the address of the pointer and assign to it.
To get the address of a variable, you use the &-operator. This is what your example does. To assign to the memory-location where x is stored, you would use the derefence-operator again like this: *k = 0;
Note that the derefence-operator and the * to express a pointer type are two different things. * and & are each other's inverse (overloading aside) operators, while int * is a type.
In C++ in particular, if the & is used together with a type, the type of the variable is a reference-type, e.g. const string &s. Just like the pointer-type this is different from the address-of operator. Reference-types do not need to be derefenced using *, but will direcly modify the memory location they reference.

Pointer operator (*) is used whenever you want to point to a variable.
Address operator (&) is used whenever you point to the memory address of a variable.

Related

What is the difference between a pointer set to a value and a pointer set to the address of a value?

I've got two questions, really. The first has to do with the interaction between a pointer and a variable, and the second has to do with the interaction between a pointer and an array. What is the best way to understand this?
I understand that a pointer contains the address to a variable, but I'm not sure what the difference is between setting the pointer to an address and setting the pointer to a variable.
I seem to have the same problem with an array, except more complex because an array may not just have one value.
For instance:
int num = 5;
int * p;
p = num; //This results in an error
p = # //This does not
Whereas:
int num[2] = {5, 10};
p = num; //This does not result in an error
p = # //This does
For the first situation, I get an error saying, "a value of type "int" cannot be assigned to an entity of type "int *"".
For the second situation, I get an error saying, "a value of type "int (*)[2]" cannot be assigned to an entity of type "int *"".
Why is this?
EDIT: I don't believe this to be a duplicate question. Array decaying does not answer my question at all, and instead this has to do with pointer types rather than properties of arrays. This question has been answered well already, but I would like to clarify that my issue was not answered by anything having to do with array decaying.
A variable has a number of distinct properties.
Given your variable definition, which I quote here
int num = 5;
its type is int, its name is num, it is initialised with a value of 5, and its address (e.g. location in machine memory) is &num.
If I was to define a second variable immediately after
int q = 5
then this variable would (like num) have type int, and value 5, but a different name q and a different address in memory &q. Even though they have the same value, the addresses of num and q are different. That (among other things) ensures that assigning q = 6 does not change the value of num.
It goes further. The pointer in your sample
int * p;
means that p is a pointer to an int. It has type int *, so its value can be the address of an int. So the assignment
p = num; //This results in an error
doesn't work, because p has type int * and num has type int. The two types are distinct, and an int cannot be converted implicitly to an int *, so the assignment is not allowed. They are different types. In the real world, the street address of a house is something different from a house, even if there is an association between them.
However your assignment
p = # //This does not
works, because p is of type int * and &num is the address of an int so also has type int *.
However, with arrays, the rules are a little different.
int num[2] = {5, 10};
p = num; //This does not result in an error
p = # //This does
Firstly, num is an array of two int. It has name num, but its type is int[2], and its value is actually based on the pair of ints 5 and 10.
When used in an expression, num is converted to a pointer to its first element. So
p = num;
is equivalent to
p = &num[0];
The conversion of num to &num[0] is called an "array to pointer" conversion.
The second assignment you tried
p = # //This does
is different. In this case &num is the address of the array num, not the address of its first element. So &num has type int (*)[2] which (in C++) syntactically means "pointer to an array of two int".
The type of p is int * (because that's how you defined it) whereas &num gies a result with type int (*)[2]. Those types are different, so the assignment is invalid.
If you want a variable that points to an array of two int (as distinct from your p which can point at the first element of an array of int) then define
int num[2] = {5,10};
int (*q)[2]; // q has type int (*)[2]
q = num; // this will work
Then you can do, for example;
std::cout << (*q)[0] << ' ' << (*q)[1] << '\n';
to print the values 5 and 10. This works because q points at the array, *q is (a reference to) the array num, so (*q)[0] and (*q)[1] access num[0] and num[1] respectively.
Note that the parentheses () are critical in all of the above discussion. *q[0] is actually (by rules of operator precedence and associativity) equivalent to *(q[0]) which is something quite different from (*q)[0]. I'll leave working out what *(q[0]) is (or is not) an exercise.
Pointers are a big hurdle to come across for new programmers.
Let me try to put it in the most easiest way I can.
Pointers are a data type in languages like C and C++ which point to a specific "memory location" specified by the pointer's type, meaning only a int pointer can point to a int memory location.
In your first example,
p = num
gives an error because you are trying to point the pointer to a value, but pointers cannot point to values but instead only memory locations. That is why
p = &num
works.
In your second example,
p = num
works because for arrays and structs in c and c++, setting the pointer directly to them automatically points to the first memory address specified by the array.
Arrays are not special data types by themselves but rather sequences of values right after one another in memory.
But,
p = &num
doesn't work because you are trying to point to the memory location of a memory location. num already points to the first location in the array, and &num points to the memory location of that location. That is why it's an error.
Hope you got it!

Clarification on "saying" pointer declarations

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

Why can't I directly assign an int to an int pointer like this: int *p = 6;?

error: invalid conversion from 'int' to 'int*'
int *q = 8;
Works fine.
*q = 6;
Why can't I directly assign an int to an int pointer like this: int *q = 6; and I can assign it safely in the next line?
Because they're different things at all. The 1st one is definition of variable with initializer expression, i.e an initialization (of the pointer itself):
int * q = 8;
~~~~~ ~ ~~~
type is int*; name of variable is q; initialized with 8
The 2nd one is assignment (of the object pointed by the pointer):
*q = 6;
~~ ~~~
dereference on q via operator*; assign the resulting lvalue pointed by q to 6
And, int *p = 6; means define a variable named p with type int* and initialize it with 6, which fails because 6 can't be used for initializing a pointer directly (i.e. the error "invalid conversion from 'int' to 'int*'").
* symbol is reused for two different purpuses in your snippet. First time it is used as a part of type declaration int *, declaring a pointer to int. Second time it is used to dereference a pointer *q, invoking indirection operator.
* can also be used to invoke multiplication operator *q = *q * *q;;
To assign a value to an integer pointed by pointer you need to dereference it. And to assigning integral value other than 0 to a pointer itself (that is what int *q = 8; is doing) requires reinterpret_cast, hence you get this error.
Statement int *q defines a variable of type "pointer to integer", and an initialisation therefore needs to be a pointer value, not an integral value.
So int *q = 8 is not the same as int *q; *q = 8 (which would be undefined behaviour because it dereferences an uninitialized pointer), but more like int *q; q = 8, which makes the misunderstanding more transparent.
This:
int *q = 8;
is an initialization. It initializes q (the pointer), not *q (what it points to). Writing this equivalently with an assignment instead of initialization would look like:
int *q;
q = 8;
So you see it doesn't make sense. (and, isn't allowed of course -- an int is not a pointer)
Just to be sure, if you write:
int *q;
*q = 8;
this is syntactically correct, but undefined behavior. Your pointer doesn't point to an object of type int, it is uninitialized and probably pointing to some invalid location. Writing there, anything could happen.
Because the types don't match.
The 6 itself is not a value of pointer type, it's an integer so it cannot be directly stored in a pointer.
When you do *q = 6 the * dereferences the pointer, so the type becomes int (or rather an lvalue int, i.e. something that can be assigned to).
Here, assign the value 8 to an object of type int*. It means q points on address 8 on memory.
int *q = 8;
Is equivalent to:
int *q;
q = 8;
Is Not equivalent to:
int *q;
*q = 8;
is illegal, as it involves constraint violation.
Related stack overflow question: Is it possible to initialize a C pointer to NULL?
A pointer variable holds an address, or 'location' of something. Thus, the pointer holds a value that is a memory address. When you say:
int *q = 6;
you are creating a pointer variable that intends to point to an int, and telling it to point to the int value stored in the address 6, which is (probably) not what you really intended.
A pointer variable should point to some memory address that contains some actual data you want to access. For example:
int x = 5;
int *q = &x;
This creates a variable (x) that contains the value 5.
the next line creates a pointer variable that contains the address of x. You have set the pointer variable 'q' to the address of the int variable 'x'.
Now you can see what is at 'x' by doing this:
int y;
y = *q;
This says "take what is pointed to by q, and store it in y". The end effect is that y will be set to 5.
int x = 5; // create variable x and set it to 5
int *q = &x; // create int pointer variable, set it to the address of x
int y; // create variable y
y = *q; // take the value pointed to by q, and store it in y
If, for example the variable x is at memory location 1234, and you looked at the value stored in 'q', it would be 1234, which is the address of x.
When you say "y = *q", you are saying "take the value stored in the address 1234, and puts that value in y". Since the memory location 1234 is 'x', and 'x' was assigned the value 5, the value 5 will be what is stored at the address 1234.
y = *q;
will take the value stored in the address 1234 and assign y to that value, thus making y 5, which was the value stored in x, which is what q 'points' to.
This could be shortened to:
int x = 5;
int *q = &x;
int y = *q;
When you write
int *q = 8; it means you declared a pointer q and initialized a pointer with the integer 8. but q being a pointer expects a address value therefore you get error stating incompatibility.
Whereas when you write
*q=8 after declaring, it means you are dereferencing the addresses pointed by q and writing a value to that location. here q points to a int so you are writing 8 a integer value to the location pointed by q. that is right. This can also lead to error at runtime if q is not initialized to point to right location.
In your first statement you are declaring and initializing the pointer to some value of type int (on the same line). In your second statement you are changing the value pointed to by a pointer. Two different things. What you have there is initialization followed by an assignment. Don't let the * confuse you.
Because it is not valid C, simple as that. Specifically, it is a constraint violation of the assignment operator, since integer to pointer or pointer to integer is not valid forms of "simple assignment" (C11 6.5.16.1).
You can convert between integers and pointers by adding an explicit cast. The result is however not guaranteed to work: pointers and integers may have different representations and there might be alignment issues.
In case of *q = 6; you assign an int to an int, which is of course perfectly fine (given that the pointer points at allocated memory somewhere).
If you re-write it like this:
int* q = 8;
*q = 6;
Then you can see the * has two different purposes.
Try
int *q = new int(8);
But working with pointers here is not normally required. If you have to use pointer, use smart pointer shared_ptr<int> or uniqe_ptr<int>.
In this case you are assigning value 8 to pointer *q and it wont work during initialization, Memory address is unique at that time not available to assign but you can set once memory block created after initialization for *q.

What exactly is the purpose of the (asterisk) in pointers?

I'm new to programming and I'm trying to wrap my head around the idea of 'pointers'.
int main()
{
int x = 5;
int *pointerToInteger = & x;
cout<<pointerToInteger;
}
Why is it that when I cout << pointerToInteger; the output is a hexdecimal value, BUT when I use cout << *pointerToInteger; the output is 5 ( x=5).
* has different meaning depending on the context.
Declaration of a pointer
int* ap; // It defines ap to be a pointer to an int.
void foo(int* p); // Declares function foo.
// foo expects a pointer to an int as an argument.
Dereference a pointer in an expression.
int i = 0;
int* ap = &i; // ap points to i
*ap = 10; // Indirectly sets the value of i to 10
A multiplication operator.
int i = 10*20; // Needs no explanation.
One way to look at it, is that the variable in your source/code, say
int a=0;
Makes the 'int a' refer to a value in memory, 0. If we make a new variable, this time a (potentially smaller) "int pointer", int *, and have it point to the &a (address of a)
int*p_a=&a; //(`p_a` meaning pointer to `a` see Hungarian notation)
Hungarian notation wiki
we get p_a that points to what the value &a is. Your talking about what is at the address of a now tho, and the *p_a is a pointer to whatever is at the &a (address of a).
This has uses when you want to modify a value in memory, without creating a duplicate container.
p_a itself has a footprint in memory however (potentially smaller than a itself) and when you cout<<p_a<<endl; you will write whatever the pointer address is, not whats there. *p_a however will be &a.
p_a is normally smaller than a itself, since its just a pointer to memory and not the value itself. Does that make sense? A vector of pointers will be easier to manage than a vector of values, but they will do the same thing in many regards.
If you declare a variable of some type, then you can also declare another variable pointing to it.
For example:
int a;
int* b = &a;
So in essence, for each basic type, we also have a corresponding pointer type.
For example: short and short*.
There are two ways to "look at" variable b (that's what probably confuses most beginners):
You can consider b as a variable of type int*.
You can consider *b as a variable of type int.
Hence, some people would declare int* b, whereas others would declare int *b.
But the fact of the matter is that these two declarations are identical (the spaces are meaningless).
You can use either b as a pointer to an integer value, or *b as the actual pointed integer value.
You can get (read) the pointed value: int c = *b.
And you can set (write) the pointed value: *b = 5.
A pointer can point to any memory address, and not only to the address of some variable that you have previously declared. However, you must be careful when using pointers in order to get or set the value located at the pointed memory address.
For example:
int* a = (int*)0x8000000;
Here, we have variable a pointing to memory address 0x8000000.
If this memory address is not mapped within the memory space of your program, then any read or write operation using *a will most likely cause your program to crash, due to a memory access violation.
You can safely change the value of a, but you should be very careful changing the value of *a.
yes the asterisk * have different meanings while declaring a pointer variable and while accessing data through pointer variable. for e.g
int input = 7;
int *i_ptr = &input;/*Here * indicates that i_ptr is a pointer variable
Also address is assigned to i_ptr, not to *iptr*/
cout<<*i_ptr;/* now this * is fetch the data from assigned address */
cout<<i_ptr;/*it prints address */
for e.g if you declare like int *ptr = 7; its wrong(not an error) as pointers ptr expects valid address but you provided constant(7). upto declaration it's okay but when you go for dereferencing it like *ptr it gives problem because it doesn't know what is that data/value at 7 location. So Its always advisable to assign pointers variable with valid addresses. for e.g
int input = 7;
int *i_ptr = &input;
cout<<*i_ptr;
for example
char *ptr = "Hello"; => here * is just to inform the compiler that ptr is a pointer variable not normal one &
Hello is a char array i.e valid address, so this syntax is okay. Now you can do
if(*ptr == 'H') {
/*....*/
}
else {
/*.... */
}

Assigning int value to an address

I thought the following codes were correct but it is not working.
int x, *ra;
&ra = x;
and
int x, ra;
&ra = x;
Please help me if both of these code snippets are correct. If not, what errors do you see in them?
Your both expressions are incorrect, It should be:
int x, *ra;
ra = &x; // pointer variable assigning address of x
& is ampersand is an address of operator (in unary syntax), using & you can assign address of variable x into pointer variable ra.
Moreover, as your question title suggests: Assigning int value to an address.
ra is a pointer contains address of variable x so you can assign a new value to x via ra
*ra = 20;
Here * before pointer variable (in unary syntax) is deference operator gives value at the address.
Because you have also tagged question to c++ so I think you are confuse with reference variable declaration, that is:
int x = 10;
int &ra = x; // reference at time of declaration
Accordingly in case of the reference variable, if you want to assign a new value to x it is very simply in syntax as we do with value variable:
ra = 20;
(notice even ra is reference variable we assign to x without & or * still change reflects, this is the benefit of reference variable: simple to use capable as pointers!)
Remember reference binding given at the time of declaration and it can't change where pointer variable can point to the new variable later in the program.
In C we only have pointer and value variables, whereas in C++ we have a pointer, reference and value variables. In my linked answer I tried to explain differences between pointer and reference variable.
Both are incorrect.
When you declare a pointer, you assign it the address of a variable. You are attempting the other way round. The correct way would be:
int x,*ra;
ra = &x;
Both of those causes, in the way you have them in your question, undefined behavior.
For the first, you don't initialize the pointer, meaning it points to a random location (or NULL if the variable is global).
For the second, you try to change the address the variable is located at, which (if it even would compile) is not allowed.
Here's some annotated code:
int main () {
// declare an int variable
int x = 0;
// declare a pointer to an int variable
int *p;
// get the memory address of `x`
// using the address-of operator
&x;
// let `p` point to `x` by assigning the address of `x` to `p`
p = &x;
// assign `x` a value directly
x = 42;
// assign `x` a value indirectly via `p`
// using the dereference operator
*p = 0;
// get the value of `x` directly
x;
// get the value of `x` indirectly via `p`
// using the dereference operator
*p;
}
Note that dereferencing a pointer that doesn't point to a valid object of the specified type is not allowed.
So you normally shouldn't do things like the following (unless you really know what you are doing):
*(int*)(12345) = 42; // assign an integer value to an arbitrary memory address
Here is my 2 cent.
If you are going onto understanding pointer in C. First make the distinction between * the operator and * the type qualifier/specifier.
See that in C * is a syntaxique element that can plays both role but never at the same time. A type qualifier:
int a;
int * c = &a;
int * my_function_returning_pointer();
And for getting the proper int. As an operator. ( *c is an alias of a)
*c = 9;
I admit that is quite confusing and can trap a lot of beginner. Make sure that you recognize when * is used as an operator or when it is used as a type qualifier.
The same things apply to & although it is less often used as type qualifier.
int & f = returning_a_reference();
int my_function( int & refParam);
It is more often use for getting the address of an object. Thus it is used as an operator.
c = &f;
case 1:
int x,*ra;
&ra = x;
it is wrong in c, because in c we can point to a memory location by using a pointer ( i.e *ra in your case ). this can be done as fallows
int x, *ra; x ---------
ra=&x; ra --->1000 | value |
----------
NOTE : with out initializing a variable we can't use pointer to hold the address of that variable, so you better to first initialize variable, then set pointer to that memory location.
int x, *ra;
x=7;
ra=&x;
Fallowing may be helpful to you:
problems(mistake we do ) in handling pointers :
1.)
int a ,*p;
p=a; // assigning value instead of address. that leads to segmentation fault at run time.
2)
int a, *p;
&p=a; // look at here wrong assignment
3)
char *p="srinivas"
strcat(p, "helo" ) ; // we cant add a substring to the constant string.
4) int a=5, *p;
p=5; // the pointer here will points to location 5 in the memory, that may damage whole system, be care full in these type of assignments.