Trying to understand this variable definition - c++

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

Related

Can anybody explain why *var=i is valid [duplicate]

char a[] = "hello";
My understanding is that a acts like a constant pointer to a string. I know writing a++ won't work, but why?
No, it's not OK to increment an array. Although arrays are freely convertible to pointers, they are not pointers. Therefore, writing a++ will trigger an error.
However, writing
char *p = a;
p++;
is fine, becuase p is a pointer, with value equal to the location of a's initial element.
a++ is not well-formed since a decays to a pointer, and the result of the decay is not an lvalue (so there is no persistent object whose state could be "incremented").
If you want to manipulate pointers to the array, you should first create such a pointer:
char* p = a; // decayed pointer initializes p
a++; // OK
++a; // even OKer
This is a very good question actually. Before discussing this, let's back to the basic concepts.
What happens when we declare a variable ?
int a=10;
Well, we get a memory location to store the variable a. Apart from this an entry is created into Symbol table that contains the address of the variable and the name of the memory location (a in this case).
Once the entry is created, you can never change anything into the symbol table, means you can't update the address. Getting an address for a variable is not in our hand, it's done by our computer system.
Let's say, we get address 400 for our variable a.
Now computer has assigned an address for the variable a, so at a later point, we can't ask computer to change this address 400 because again, it's not in our hand, our computer system does it.
Now you have an idea about what happens when we declare a variable.let's come to our question.
Let's declare an array.
int arr[10]
So, when we declare this array, we create the entry into the symbol table and, store the address and the name of the array into the symbol table.
let's assume we get address 500 for this variable.
Let's see what happens when we want to do something like this :
arr++
when we increment arr, we want to increment 500, that is not possible and not in our hand, because it has been decided by the computer system, so we can't change it.
instead of doing this we can declare a pointer variable
int * p= &arr;
What happens in this situation is: again an entry is created into the symbol table that stores the name and the address of the pointer variable p.
So when we try to increment p by doing p++, we are not changing the value into the symbol table, instead we are changing the value of the address of the pointer variable, that we can do and we are allowed to do.
Also it's very obvious that if we will increment the a the ultimately we are going to loss the address of our array. if we loss the address of array then how will we access the array at a later point ?
It is never legal in C to assign to an expression of array type. Increment (++) involves assignment, and is thus also not legal.
What you showed at the top is a special syntax for initializing a char array variable.
I think this answer here explains "why" it's not a good idea;
It's because array is treated as a constant pointer in the function it is declared.
There is a reason for it. Array variable is supposed to point to the first element of the array or first memory instance of the block of the contiguous memory locations in which it is stored. So, if we will have the liberty to to change(increment or decrement ) the array pointer, it won't point to the first memory location of the block. Thus it will loose it's purpose.

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

Is the name of a two dimensional array address of the address of its first element in C++?

When implementing a two dimensional array like this:
int a[3][3];
these hold: A=&A[0], at the same time A[0]=&A[0][0]. So, A=&(&A[0][0]), what basically says that A is the address of the address of the first element of the array, which is not quite true. What is my mistake here? Does A really decay to a pointer to a pointer?
Your mistake is that you have an incorrect understanding of the relationship between arrays and pointers. An array is not a pointer. It is an array. However, an array is implicitly convertible to a pointer to its own first element. So, while this expression does evaluate to true:
A == &A[0]
It is not correct to say that A is &A[0]. The conversion does not happen in all expressions. For example:
&A
This does not take the address of the address of the first element of A (that doesn't even make sense). It takes the actual address of A, who's type is int[3][3]. So the type of &A is int(*)[3][3], read as "pointer to array of 3 arrays of 3 ints".
The primary difference between &A and &A[0] is that if you add 1 to &A, you will get an address that is 3 * 3 * sizeof(int) bytes away, while if you add 1 to &A[0], you will get a pointer that is only 3 * sizeof(int) bytes away.
With all this in mind, you should be able to see where your mistake is. A[0] is not &A[0][0], but it is implicitly convertible to it. However, like all conversions, this results in a temporary, which you cannot take the address of. So the expression &(&A[0][0]) doesn't even make sense.
Because of reactions on my previous answer I did some research to learn more on whatever was wrong in my explanation.
Found a rather elaborate explanation of the topic here :
http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c
I'll try to summarize :
if you have following :
char array_place[100] = "don't panic";
char* ptr_place = "don't panic";
the way that this is represented in memory is entirely different.
whereas ptr_place is a real pointer, array_place is just a label.
char a = array_place[7];
char b = ptr_place[7];
The semantics of arrays in C dictate that the array name is the address of the first element of the array, which is not the same as saying that it is a pointer. Hence in the assignment to a, the 8th character of the array is taken by offsetting the value of array_place by 7, and moving the contents pointed to by the resulting address into the al register, and later into a.
The semantics of pointers are quite different. A pointer is just a regular variable that happens to hold the address of another variable inside. Therefore, to actually compute the offset of the 8th character of the string, the CPU will first copy the value of the pointer into a register and only then increment it. This takes another instruction [1].
This point is frequently ignored by programmers who don't actually hack on compilers. A variable in C is just a convenient, alphanumeric pseudonym of a memory location. Were we writing assembly code, we would just create a label in some memory location and then access this label instead of always hard-coding the memory value - and this is what the compiler does.
Well, actually the address is not hard-coded in an absolute way because of loading and relocation issues, but for the sake of this discussion we don't have to get into these details.
A label is something the compiler assigns at compile time. From here the great difference between arrays and pointers. This also explains why sizeof(array_place) gives the full size of the array where as the size of a pointer will give the size of a pointer.
I must say, I was not aware of these subtle differences myself, and I have been coding for quite a long time in C and C++ and with arrays too.
Nevertheless if the name of the array element is the address of the first element of the array. You can create a pointer and initialise it what that value
char* p = array_place
p will point to the memory location where the characters are.
to conclude :
There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so p=array_place and p++ are legal. But an array name is not a variable; constructions like array_place=p and array_place++ are illegal. That I did know ;-)

why these 3 lines code are right?About *p

int *p;
scanf("%d",&p);
printf("%d\n",p);
In my past understandings,the "p" is a address,but now it seems that the p is a simple variable.
I cant understand why these 3 lines code are right!!!
can you help me?
This will only work as long as a pointer is the same size as an integer because you are basically treating the pointer as an integer. That is, if int is a 32-bit integer, and a pointer void* is a 32-bit address.
The way it should be written:
int p; // not the lack of the *
scanf("%d",&p); // this gives scanf the address of p
printf("%d\n",p); // this uses p's value
Which will actually use p as an integer instead of declaring it as a pointer and treating it like an integer.
They are not right. They just seem to work, because you ask scanf to store an integer and the address where to store it is the address of the pointer p. You are basically treating the storage of the pointer itself as the storage of an integer. Likewise for printf, you pass the address of the pointer (which contains the integer) and ask printf to read it from there as... an integer. You could even change the first line to
float* p;
and it would still seem to work. In the end, this is a good example of why you should avoid C-style interfaces which are not type-safe.
If I will explain through your statements, then it will be
int *p; //Declaration of pointer variable p, which can hold the address of integer variable
scanf("%d",&p); //Getting input, will be stored at address of pointer variable p
printf("%d\n",p); //It will display the value stored at &p
The code above is not really correct, and it is built on top of a fair amount of assumptions and C constructs.
The first assumption is that a pointer and an int have the same size, which will break in most (all I know) 64bit platforms. It is then using a type unsafe interface (variadic function arguments) to pass the address of an int* as if it was the address of an int. The code inside the scanf will assume that it is writting to an int and write over the bits... but the type is not an int* and that bit pattern might or not make sense even in the platforms where the sizeof(int) = sizeof(int*)
That code is not right at all.
Some (bad) compilers may be unable to detect the problems because both printf and scanf are variadic functions... but for example g++ would warn you that the types passed don't match with the ones specified in the format strings.

Why does binary saving of array in a file works? [C++]

C++ newbie here.
I'm trying to figure out the following line that writes a buffer into a file:
fOut.write((char *)&_data, sizeof(_data));
_data = array of integers...
I have a couple of questions:
Is &_data the address to the first element of the array?
Whatever address it is, does that mean that we only save the address of the array? then how come I still can access the array after I free it?
Shouldn't I pass sizeof(_data)*arrLength? what is the meaning of passing the size of int (in this case) and not the size of the entire array?
What does casting into char* mean when dealing with addresses?
I would really appreciate some clarifications.
Contrary to your comment, the array must be automatic or static storage duration in order for sizeof to work.
It should be just (char*)_data. The name of an array implicitly converts to a pointer to the first element.
No, write expects a pointer, and stores the content found at that location, not the location's address.
No. Since _data is an array, sizeof (_data) is the cumulative size of all elements in the array. If _data were a pointer (such as when an array is dynamically allocated on the heap), you would want numElems * sizeof(_data[0]). Multiplying the size of a pointer by the number of elements isn't helpful.
It means that the content at that address will be treated as a series of individual bytes, losing whatever numeric meaning it might have had. This is often done to perform efficient bulk copy of data, either to and from a file, or with memcpy/memmove. The data type should be POD (plain old data) or you'll get unexpected results.
If _data is a pointer to an array allocated from the heap, as your comment suggests, then the code is badly broken. In that case, you are saving just the address, and it may appear to work if you load the file back into the same instance of your program, but that's just because it's finding the data still in memory at the same address. The data wouldn't actually be in the file, and if you re-started the program before loading the file, you'd find that the data was gone. Make the changes I mentioned in both (1) and (3) in order to save the complete array regardless of whether it's allocated automatic, static, or dynamically.
What does casting into char* means
when dealing with addresses?
Imagine this simple example
int x = 12;
char * z = (char *)&x;
And assume an architecture where int is 4 bytes long. From the C++ Standard sizeof(char)==1.
On the expression char * z the char * part, you could say that is being used for pointer arithmetic
on the Second line of the example I gave, what happens is that z now points to the first (out of 4 bytes) that x has. Doing a ++z; will make z point to the Second Byte of the (in my example) 4byte int
You could say that the left part of a declaration is used for pointer arithmetic, to simplify things. a ++(char *) would move you by one byte, while a ++(int *) would move you by the corresponding number of bytes int occupies on the memory.
Yes
No, write uses this address as the first location, and reads through sizeof(_data) writing the whole array
sizeof(_data) will return the size of the entire array not the same as sizeof(int)
Means the data will be read byte by byte, this is the pointer required by write as it writes in binary format(byte by byte)
1) Yes, &_data is the address of the first element of your array.
2) No, write() writes the number bytes you have specified via sizeof(_data) starting at address &_data
3) You would pass sizeof(int)*arrLength if _data is a pointer to an array, but since it is an array sizeof() returns the correct size.
4) don't know. ;)
read this : http://www.cplusplus.com/reference/iostream/ostream/write/
should be.
if you call "fstream.write(a,b)" then it writes b bytes starting from location a into the file (i.e. what the address is pointing at);
it should be the size in bytes or chars .
not much, similar to casting stuff to byte[] in more civilized languages.
By the way, it will only work on simple arrays with simple values inside them...
i suggest you look into the >> << operators .
is &_data the address to the first element of the array?
Yes, it is. This is the usual way to pass a "reference" to an array in C and C++. If you passed the array itself as a parameter, the whole array contents would be copied, which is usually wasteful and unnecessary. Correction: You can pass either &_data, or just _data. Either way, the array does not need to be copied to the stack.
whatever address it is, does that mean that we only save the address of the array? then how come I still can access the array after I delete him from the memory?
No, the method uses the address it gets to read the array contents; just saving the memory address would be pointless, as you point out.
Shouldn't I pass sizeof(_data)*arrLength? I mean...
what is the logic of passing the size
of int (in this case) and not the size
of the entire array?
No, sizeof(_data) is the size of the array, not of one member. No need to multiply by length.
What does casting into char* means when dealing with addresses?
Casting to char* means that the array is accessed as a list of bytes; that's necessary for accessing and writing the raw values.