Am I understanding pointers correctly? C++ - c++

I am learning about pointers in C++ and I have read an article on it and I think I understand it, though I just wanted some clarification on the pseudo code I wrote.
int someGameHealthAddress = 1693;
int healthIWantItToBe = 20;
int * newHealthValue;
newHealthValue = someGameHealthAddress;
*newHealthValue = healthIWantItToBe;
So is the above right? Like the way it works?
EDIT: Thank you all for answering, glad I got this down now. You've been a large help :)
EDIT2: I'm quite proud I've got the hang of this now. By the looks of it a lot of people have trouble understanding pointers.

If someGameHealthAddress is supposed to be an address then you need to declare it as such. E.g:
int someGameHealth = 1693;
int healthIWantItToBe = 20;
int * someGameHealthAddress; //this is the pointer to an int, which is basically its address
someGameHealthAddress = &someGameHealth; // take address of someGameHealth
*someGameHealthAddress = healthIWantItToBe; // modify the value it points to
In your code this line was wrong:
newHealthValue = someGameHealthAddress;
Because it missmatches the types of variables, it's like int* = int.
Note, that this is possible to cast from and integer type to pointer type, it's almost always a bug, because you nearly never know the absolute value of variable's address in memory. You usually locate something, and then work with relative offsets. This is usually the case when you are doing some in-memory hacking, which your example seems to be.

Almost. In order to get a pointer to a variable, you need the "address of" operator &:
// Set newHealthValue to point to someGameHealth
newHealthValue = &someGameHealth;
(I removed "Address" from the variable name, since it isn't an address. The pointer now contains its address).
Then your final line of code will change the value of the object that newHealthValue points to, i.e. it will change someGameHealth.

This statement is wrong:
newHealthValue = someGameHealthAddress;
Because the left side has type pointer and right side is an integer. You have to make sure types match in assignments. To get the address of the someGameHealthAddress, use &:
newHealthValue = &someGameHealthAddress;
Now the types match because the right side is an address of integer, and thus a pointer.

Depending if you want the value of the pointer to be 1693, or you want the pointer to point to the address of the variable someGameHealthAddress
1.assigns newHealthValue value to someGameHealthAddress value
*newHealthValue = someGameHealthAddress;
assigns the newHealthValue to point to the address of the someGameHealthAddress variable
*newHealthValue = &someGameHealthAddress;
assigns the address of newHealthValue to the value of the someGameHealthAddress variable
&newHealthValue = someGameHealthAddress;
assigns the address of the newHealthValue to the address of the someGameHealthAddress variable
&newHealthValue = &someGameHealthAddress;

* and & are two operators used in c++
& means "the address off"
ie, &p means address of p .
* means "value in the location"
*p means value in the address stored in p.
For that p must me a pointer.(because p should keep an address).
Here newHealthValue = someGameHealthAddress; will give compilation error.because someGameHealthAddress is an integer and newHealthValue is integer pointer.
int*=int is type miss-match
You can store the address of someGameHealthAddress using the following statement
newHealthValue = &someGameHealthAddress;
which means newHealthValue = (address of)someGameHealthAddress
*newHealthValue = healthIWantItToBe; is syntactically correct because it stores the value of healthIWantItToBe to the address pointed by newHealthValue

Related

If * means pointing to the adress of a variable, why is e.g (int*)var not pointing to var?

int var = 100;
cout << (int*)var<< endl;
cout << &var<< endl;
(int*)var printed just 100 in hex, which I don't quite understand. Can you explain why it is doing so?
I would like to know other ways of pointing to an address without creating a complete new pointer variable.
What you have just written does not make sense. First you say:
int var = 100;
... but then you typecast the value of var into "a pointer to an int":
(int *)var
The only reason why it didn't crash-and-burn is that you did not actually try to use that pointer to access something in memory. But, cout was smart enough to realize, "say, the programmer says that this is a pointer." So it printed, in hex, the value of the pointer itself, not any data that the pointer was supposedly pointing at.
Just To Be Clear:
(int *)var does not mean "point to the address of a variable." (If you want "the address of something," albeit not "a pointer to the same", use &var). Instead, this is just a typecast, which in this case means: "treat the value of var as 'a pointer to an int'."
If * means pointing to the adress of a variable, then...
Does * mean "pointing to the adress of a variable" though? What do you think this means?
21 * 2
* means different things in different contexts. In a type name, it means that the type is a pointer. In an expression it is an operator. In case the operator is binary and operands are numbers, it means multiplication. In case the operator is unary and the operand is a pointer, it means indirection through that pointer.
(int*)var printed just 100 in hex, which I don't quite understand. Can you explain why is it doing so
This is how reinterpreting an integer to a pointer type typically works. The value was 100, and the value remained 100 when you reinterpreted it as a pointer.
Strictly speaking, the conversion isn't meaningfully defined for integer types that aren't large enough to represent all pointer values, so converting an int doesn't make sense.
I would like to know other ways of pointing to an adress without creating a complete new pointer variable.
You've shown a way how to do that: &var. That creates a pointer object pointing to var without creating a pointer variable. Another way to create a pointer prvalue is use this keyword in a member function, or call a function that returns a pointer.

How to change the address a pointer is pointing to in C++

While experimenting with pointers, I had the idea to change the address a pointer. I tried the following:
int* pointer;
&pointer = 0x28ff0d; //To point to an empty space in memory
But that threw out an error (Details: (here) in line 2, lvalue required as left operand [...]), so I guess it's impossible? I'm not trying to make a nullpointer, but litterally to change the memory address
For obvious reasons, setting a pointer to a hardcoded address is a bad idea. But, you can do so by reinterpret_cast<>ing the address to the type you're assigning it to, like so:
int * pointer = reinterpret_cast<int *>(0xDEADBEEF);
or
int * pointer = &some_int;
. . .
pointer = reinterpret_cast<int *>(0xDEADBEEF);
Note that dereferencing pointer in this case is undefined behavior... but doing this might still be useful for something like debugging a use-after-free, where a sentinel value like 0xDEADBEEF would clearly communicate that you had already freed that memory.
Obviously the much more common, useful, and safe case for changing the address you are pointing to would be to take the address of a different (real) piece of data:
int * pointer = &some_int;
int new_val = 1234;
pointer = &new_val; // *pointer is now 1234
You can never change the address of a variable. So whatever T is (be it an intrinsic type like int or double, a struct, a pointer or an array, the following is forbidden in C++:
T var;
&var = anything; // WRONG! &var is not a lvalue
The error lvalue required as left operand means that you can only assign to something that can receive a new value, and the address of a variable is not.
A pointer is a variable. Any variable has an address where it's located. So if you've declared a varible like e.g. int x;, then &x is the address where that variable resides.
A pointer is a variable which resides somewhere, but in addition it has a value, which happens to be an address of some other variable. So if you've declared a pointer int* x;, have written something to it, then x will represent some address you've written to it, and *x will be the value pointed to by the pointer.
So your syntactic mistake was using & where you should have just used the variable name, without &. After this is clear, be sure to read the other answers which explain further problems with your code.
int* pointer;
&pointer = 0x28ff0d;
This will throw error because &pointer is not an lvalue. On the left side of the assignment operator there must be an lvalue.

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*.

Trying to understand this variable definition

What exactly does this do?
int test = *(int*)(0x154512);
0x154512
is an integer, written in base 16.
(int*)(0x154512)
says to treat that number as the address of an int variable.
*(int*)(0x154512)
says to dereference that address, or get the int value at that address.
int test = *(int*)(0x154512)
says to declare the int variable test and assign it the int value located at address 0x154512.
Let's break this down into pieces.
0x154512 is a hex value, or base-16, which is often used for memory addresses for convenience reasons.
int* declares a pointer to a value of type int. So, (int*)(0x154512) means 0x154512 is being treated as a memory address, which we expect to hold an integer.
The last * on the left is the dereference operator, which means "get the value located at this pointer" more or less.
So it copies the integer at memory address 0x154512 to the variable "test".
For more information on pointers:
http://www.cplusplus.com/doc/tutorial/pointers/
If you're planning to do a lot of C++ in the future, make sure to give this a nice, long read. Pointers are fun.
One line get integer value stored at 0x154512 memory location

C++ Array Inquiry

Why can we do:
char* array = "String";
but not
int* array = 1;
To my understanding * means address, so I don't really understand why we can give a non-address value, like "String." to char* array.
char* array means that array is a variable that can hold the address of another object (such as another variable or constant).
If the program has "String", it means that there is actually an array of 7 characters that exists in memory somewhere and it holds the contents "String".
When you write array = "String"; then the variable array is made to hold the address of the letter 'S' in that string.
This is because C++ has a rule, sometimes called array-pointer decay which means that if you try to use an array (such as "String") in a context where a value is expected, then it gets automatically converted to a pointer to the first element of that array.
Without that rule you'd have to write array = &("String"[0]); . The rule was included in C originally to avoid having to write &....[0] all over the place when working with arrays, although in hindsight it seems to have generated more pain than pleasure.
Moving onto int* i = 1. You have said that i can hold the address of an int, but you have not provided any such address. Variables thare aren't arrays don't automatically get converted to their address. In fact 1 isn't even a variable. We call it a prvalue , it doesn't have any memory storage area associated with it, so it does not have an address. To point at an instance of a 1 you would have to make a variable, for example:
int j = 1; int* i = &j;
* does not mean adress. Its meaning is context sensitive, but most of the time it means pointer.
The reason for this, not to work is because "String" is an array of characters, or a pointer to an character. In contrast to this, 1 is a literal which is not a valid adress. You should write int array = 1 instead, and after that you could do int *brray = &array.
* means a pointer, not an address. You can retrieve an address using the & operator.
char* array = "String";
Actually declares array as a pointer to a character, and the = sign after the declaration tells the compiler what value should the pointer posses. In this case it's an address of "String" in the string pool somewhere in the memory of the run program.
int* array = 1;
Doesn't put the address of 1 to array as you may expect. However, with a little adjustment
int* array = (int*)1;
... it could point to an integer at address 1, which is unfortunately unaccessible.
This assignment:
char* array = "String";
Assign "String" to an available location in memory and returns the memory address of the first position of "String" in memory. "array" stores the address of "S".
This assignment:
int* array = 1;
Doesn't work because you are trying to assign an integer to a pointer to integer. The types are different
"I don't really understand why we can give a non-address value, like "String." "
That's because a character string literal actually is const char[] array, which decays to a pointer when assigned to a char*, while 1 isn't one and you can't take it's address in any way.