We know integer variable take 4-byte memory address. I just wonder, if we initialize integer variables and make a pointer to it. I can get the value of it from the pointer (which have the address of the variable: 0x22fef8 in my computer). But how about the memory address after 0x22fef8 which is 0x22fef9, 0x22fefa, 0x22fefb? What is in there? Are we will get the value of the variable if we dereference this address? How to access them?
You're right: in a 32-bit computer an integer takes up four bytes. In C, that can be expressed by the following code:
int i = 0x12345678;
int *p_i = &i;`
If p_i gets the value 0x22fef8, then p_i++ would become 0x22fefc since it would point to the next integer. If you want to see what's in the bytes that make up i, you need to use a different pointer:
typedef uint_8 byte;
byte *p_b = (byte *)&i;`
That means that you change the pointer-to-int that &i represents and typecast it to be a pointer-to-byte. It will still have the value 0x22fef8 since that's where the first byte of i is - but now if you do a p_b++ it will change to 0x22fef9. And note that if you print out the original value of *p_b (that is, the byte that it is pointing to), it will not give the same value as i. Depending on the computer, it will print out either the first byte or the last byte: 0x12 or 0x78, or at least the decimal versions thereof.
This is due to the "endianness" of the computer, which affects the storage of multi-byte values. Little-endian computers like the x86 store the littlest part of the value first - the 0x78 - while Power PC computers store the biggest part of the value first - the 0x12.
int types take up four bytes on your system, so those are all occupied by the int. All are inaccessible except the first one.
It is to note some ints take up two bytes on other systems. It isn't regulated by the standard.
If you want to see the values in those addresses, just do this and you will get values of next 10 addresses
int main()
{
int a = 5;
int *p_i = &a; // The address of 'a' is stored in pointer 'p_i'
// Now you want to check the values in 10 further addresses
for ( int i = 0; i < 10; i++ )
{
int value = *p_i; // Here it is getting the address of pointer as integer value
cout << value << endl;
p_i++;
}
return 0;
}
Related
I casted the memory address from double to an integer .
Even though they point to the same address why the values are different ?
#include<iostream>
using namespace std;
int main()
{
double d = 2.5;
auto p = (int*)&d;
auto q = &d;
cout<<p<<endl; // prints memory address 0x7fff5fbff660
cout<<q<<endl; // print memory address 0x7fff5fbff660
cout<<*p<<endl; //prints 0
cout<<*q<<endl; // prints 2.5
return 0;
}
But why the value are different
0x7fff5fbff660
0x7fff5fbff660
0
2.5
Program ended with exit code: 0
Suppose you have "11" written on a piece of paper. That is eleven if it's decimal digits. That is two if there's one mark for each value. That's three if it's binary. How you interpret stored information affects the value you understand it to be storing.
double d = 2.5;
auto p = (int*)&d;
auto q = &d;
p and q are created pointing to the same memory location. The memory holds a double (usually 8 bytes)
When you create
auto p = (int*)&d;
you are telling the compiler ( reintepret_cast< int*> ( &d) ) that the value in d was an integer.
So the values of the pointers are the same, but the types are not.
When you print out
cout<<*q<<endl; // prints 2.5
You are displaying the correct value - as it came in and out through that.
when you print out
cout<<*p<<endl; //prints 0
You are looking at 4 (typically) bytes of the 8 byte memory, and interpreting them as an integer.
These happen to be 0x00, 0x00, 0x00, 0x00
It's because you've violated the strict aliasing rule, giving you undefined behavior. You cannot acesss type A through a pointer of type B and just pretend it works.
TL;DR:
if you have an int* pointing to some memory containing an int and then
you point a float* to that memory and use it as a float you break the
rule. If your code does not respect this, then the compiler's
optimizer will most likely break your code.
The memory addresses are the same, and they both point to a double-precision floating point number in memory. However, you've asked the compiler to treat one as an integer and another as a double. (A pointer might just be a memory address, but at compile-time the compiler has information about the type as well.) It just so happens that the in-memory representation of this particular double-precision number looks like a 0 when treated as an integer.
Because you have casted them to different types yourself.
When you do auto p = (int*)&d; you are asking the compiler to store a double value in a memory area allocated for an integer. An integer and a double are represented in different formats in a computer's memory. A double is stored using a floating point representation in memory, while an int is not. This is a classic example of undefined behaviour.
char b = 'a';
int *a = (int*)&b;
std::cout << *a;
What could be the content of *a? It is showing garbage value. Can you anyone please explain. Why?
Suppose char takes one byte in memory and int takes two bytes (the exact number of bytes depends of the platform, but usually they are not same for char and int). You set a to point to the memory location same as b. In case of b dereferencing will consider only one byte because it's of type char. In case of a dereferencing will access two bytes and thus will print the integer stored at these locations. That's why you get a garbage: first byte is 'a', the second is random byte - together they give you a random integer value.
Either the first or the last byte should be hex 61 depending on byte order. The other three bytes are garbage. best to change the int to an unsigned int and change the cout to hex.
I don't know why anyone would want to do this.
You initialize a variable with the datatype char ...
a char in c++ should have 1 Byte and an int should contain 2 Byte. Your a points to the address of the b variable... an adress should be defined as any hexadecimal number. Everytime you call this "program" there should be any other hexadecimal number, because the scheduler assigns any other address to your a variable if you start this program new.
Think of it as byte blocks. Char has one byte block (8 bits). If you set a conversion (int*) then you get the next 7 byte blocks from the char's address. Therefore you get 7 random byte blocks which means you'll get a random integer. That's why you get a garbage value.
The code invokes undefined behavior, garbage is a form of undefined behavior, but your program could also cause a system violation and crash with more consequences.
int *a = (int*)&b; initializes a pointer to int with the address of a char. Dereferencing this pointer will attempt to read an int from that address:
If the address is misaligned and the processor does not support misaligned accesses, you may get a system specific signal or exception.
If the address is close enough to the end of a segment that accessing beyond the first byte causes a segment violation, that's what you can get.
If the processor can read the sizeof(int) bytes at the address, only one of those will be a, (0x61 in ASCII) but the others have undetermined values (aka garbage). As a matter of fact, on some architectures, reading from uninitialized memory may cause problems: under valgrind for example, this will cause a warning to be displayed to the user.
All the above are speculations, undefined behavior means anything can happen.
I encountered the following line in a OpenGL tutorial and I wanna know what does the *(int*) mean and what is its value
if ( *(int*)&(header[0x1E])!=0 )
Let's take this a step at a time:
header[0x1E]
header must be an array of some kind, and here we are getting a reference to the 0x1Eth element in the array.
&(header[0x1E])
We take the address of that element.
(int*)&(header[0x1E])
We cast that address to a pointer-to-int.
*(int*)&(header[0x1E])
We dereference that pointer-to-int, yielding an int by interpreting the first sizeof(int) bytes of header, starting at offset 0x1E, as an int and gets the value it finds there.
if ( *(int*)&(header[0x1E])!=0 )
It compares that resulting value to 0 and if it isn't 0, executes whatever is in the body of the if statement.
Note that this is potentially very dangerous. Consider what would happen if header were declared as:
double header [0xFF];
...or as:
int header [5];
It's truly a terrible piece of code, but what it's doing is:
&(header[0x1E])
takes the address of the (0x1E + 1)th element of array header, let's call it addr:
(int *)addr
C-style cast this address into a pointer to an int, let's call this pointer p:
*p
dereferences this memory location as an int.
Assuming header is an array of bytes, and the original code has been tested only on intel, it's equivalent with:
header[0x1E] + header[0x1F] << 8 + header[0x20] << 16 + header[0x21] << 24;
However, besides the potential alignment issues the other posters mentioned, it has at least two more portability problems:
on a platform with 64 bit ints, it will make an int out of bytes 0x1E to 0x25 instead of the above; it will be also wrong on a platform with 16 bit ints, but I suppose those are too old to matter
on a big endian platform the number will be wrong, because the bytes will get reversed and it will end up as:
header[0x1E] << 24 + header[0x1F] << 16 + header[0x20] << 8 + header[0x21];
Also, if it's a bmp file header as rici assumed, the field is probably unsigned and the cast is done to a signed int. In this case it doesn't matter as it's being compared to zero, but in some other case it may.
If I declare
int x = 5 ;
int* p = &x;
unsigned int y = 10 ;
cout << p+y ;
Is this a valid thing to do in C++, and if not, why?
It has no practical use, but is it possible?
The math is valid; the resulting pointer isn't.
When you say ptr + i (where ptr is an int*), that evaluates to the address of an int that's i * sizeof(int) bytes past ptr. In this case, since your pointer points to a single int rather than an array of them, you have no idea (and C++ doesn't say) what's at p+10.
If, however, you had something like
int ii[20] = { 0 };
int *p = ii;
unsigned int y = 10;
cout << p + y;
Then you'd have a pointer you could actually use, because it still points to some location within the array it originally pointed into.
What you are doing in your code snippet is not converting unsigned int to pointer. Instead you are incrementing a pointer by an integer offset, which is a perfectly valid thing to do. When you access the index of an array, you basically take the pointer to the first element and increase it by the integer index value. The result of this operation is another pointer.
If p is a pointer/array, the following two lines are equivalent and valid (supposing the pointed-to-array is large enough)
p[5] = 1;
*(p + 5) = 1;
To convert unsigned int to pointer, you must use a cast
unsigned int i = 5;
char *p = reinterpret_cast<char *>(i);
However this is dangerous. How do you know 5 is a valid address?
A pointer is represented in memory as an unsigned integer type, the address. You CAN store a pointer in an integer. However you must be careful that the integer data type is large enough to hold all the bits in a pointer. If unsigned int is 32-bits and pointers are 64-bits, some of the address information will be lost.
C++11 introduces a new type uintptr_t which is guaranteed to be big enough to hold a pointer. Thus it is safe to cast a pointer to uintptr_t and back again.
It is very rare (should be never in run-of-the-mill programming) that you need to store pointers in integers.
However, modifying pointers by integer offsets is totally valid and common.
Is this a valid thing to do in c++, and if not why?
Yes. cout << p+y; is valid as you can see trying to compile it. Actually p+y is so valid that *(p+y) can be translated to p[y] which is used in C-style arrays (not that I'm suggesting its use in C++).
Valid doesn't mean it actually make sense or that the resulting pointer is valid. Since p points to an int the resulting pointer will be an offset of sizeof(int) * 10 from the location of x. And you are not certain about what's in there.
A variable of type int is a variable capable of containing an integer value. A variable of type int* is a pointer to a variable copable of containing an integer value.
Every pointer type has the same size and contains the same stuff: A memory address, which the size is 4 bytes for 32-bit arquitectures and 8 bytes for 64-bit arquitectures. What distinguish them is the type of the variable they are poiting to.
Pointers are useful to address buffers and structures allocated dynamically at run time or any sort of variable that is to be used but is stored somewhere else and you have to tell where.
Arithmetic operations with pointers are possible, but they won't do what you think. For instance, summing + 1 to a pointer of type int will increase its value by sizeof(int), not by literally 1, because its a pointer, and the logic here is that you want the next object of this array.
For instance:
int a[] = { 10, 20, 30, 40 };
int *b = a;
printf("%d\n", *b);
b = b + 1;
printf("%d\n", *b);
It will output:
10
20
Because b is pointing to the integer value 10, and when you sum 1 to it, or any variable containing an integer, its then poiting to the next value, 20.
If you want to perform operations with the variable stored at b, you can use:
*b = *b + 3;
Now b is the same pointer, the address has not changed. But the array 10, 20, 30, 40 now contains the values 13, 20, 30, 40, because you increased the element b was poiting to by 3.
How come you can assign an address to an integer variable like this,the complier will not give an error. i always though you can only assign integer values to a integer variable
int a=0x28ff1c
You can do the same for a char variable, the complier will not give a error
char b=0x28ff1c
It will output on the console screen rubbish value for char b and a random value for int a
cout<<b
<<endl;
cout<<a;
Can someone explain to me why there is a difference in the output for char b and int a.
Can someone aslo explain to me why a char variable and integer variable can have addresses assign to it
0x28ff1c is not an address itself - it's just a hexadecimal number.
The following are equivalent:
int a = 2686748; //decimal number
int a = 0x28ff1c; //hexadecimal number
int a = 012177434; //octal number
An address is represented by a pointer - if it's just that, an address, you can use a void*:
void* p = (void*)0x28ff1c;
In which case
int a = p;
wouldn't compile. p is an address, the number itself isn't.
The number 0x28ff1c is just the hexadecimal (base-16) representation of the decimal (base-10) number 2686748. As cout defaults to printing decimal values for integers, that is probably the number you got printed.
The case with char b = 0x28ff1c is slightly different, because
char is not large enough to hold that value. The practical result is that it gets truncated to 0x1c.
cout treats char specially, because it is normally used to hold textual data, so cout prints the character that has the code 0x1c, which is some kind of control character. You could try it with 0x41 for example (which represents 'A' in ASCII and UTF-8).
And note that there is nothing that marks 0x28ff1c as being an address. An address would be formed by &a or (void*)0x28ff1c.
Because in any literal starting 0x is actually an integer. So it is allowed. An address is can sometimes be an integer.
You can also use *(int *)(Address) = value as a construct to assigne a value to Address and use the answer by #Luchian Grigore