Value of a pointer is address of a variable. Why value of an int pointer increased by 4-bytes after the int pointer increased by 1.
In my opinion, I think value of pointer(address of variable) only increase by 1-byte after pointer increment.
Test code:
int a = 1, *ptr;
ptr = &a;
printf("%p\n", ptr);
ptr++;
printf("%p\n", ptr);
Expected output:
0xBF8D63B8
0xBF8D63B9
Actually output:
0xBF8D63B8
0xBF8D63BC
EDIT:
Another question - How to visit the 4 bytes an int occupies one by one?
When you increment a T*, it moves sizeof(T) bytes.† This is because it doesn't make sense to move any other value: if I'm pointing at an int that's 4 bytes in size, for example, what would incrementing less than 4 leave me with? A partial int mixed with some other data: nonsensical.
Consider this in memory:
[↓ ]
[...|0 1 2 3|0 1 2 3|...]
[...|int |int |...]
Which makes more sense when I increment that pointer? This:
[↓ ]
[...|0 1 2 3|0 1 2 3|...]
[...|int |int |...]
Or this:
[↓ ]
[...|0 1 2 3|0 1 2 3|...]
[...|int |int |...]
The last doesn't actually point an any sort of int. (Technically, then, using that pointer is UB.)
If you really want to move one byte, increment a char*: the size of of char is always one:
int i = 0;
int* p = &i;
char* c = (char*)p;
char x = c[1]; // one byte into an int
†A corollary of this is that you cannot increment void*, because void is an incomplete type.
Pointers are increased by the size of the type they point to, if the pointer points to char, pointer++ will increment pointer by 1, if it points to a 1234 bytes struct, pointer++ will increment the pointer by 1234.
This may be confusing first time you meet it, but actually it make a lot of sense, this is not a special processor feature, but the compiler calculates it during compilation, so when you write pointer+1 the compiler compiles it as pointer + sizeof(*pointer)
As you said, an int pointer points to an int. An int usually takes up 4 bytes and therefore, when you increment the pointer, it points to the "next" int in the memory - i.e., increased by 4 bytes. It acts this way for any size of type. If you have a pointer to type A, then incrementing a A* it will increment by sizeof(A).
Think about it - if you only increment the pointer by 1 byte, than it will point to a middle of an int and I can't think of an opportunity where this is desired.
This behavior is very comfortable when iterating over an array, for example.
The idea is that after incrementing, the pointer points to the next int in memory. Since ints are 4 bytes wide, it is incremented by 4 bytes. In general, a pointer to type T will increment by sizeof(T)
A pointer points at the BEGINNING of something in memory. An INT occupies 4 bytes (32bit) and a DOUBLE occupies 8 bytes (64bit) in memory. So if you have a DOUBLE number stored, and you wish at a very low level pointing to the next available memory location, the pointer wooud be increased by 8 bytes. If for some reason you pointed at +4bytes from the start of a DOUBLE value, you would corrupt it's value. Memory is a very large flat field that has no conscience of itself, so it's up to the software to divides it properly and to "respect the borders" of items located in that field.
Related
I have a question about pointers, and memory addresses:
Supposing I have the following code:
int * array = (int *) malloc(sizeof(int) * 4);
Now in array im storing a memory address, I know that c++ takes already care when adding +1 to this pointer it will add 4 bytes, but what If I want to add manually 4 bytes?
array + 0x004
If im correct this will lead to add 4*4 (16) bytes, but my Idea is to add manually those 4 bytes.
Why? Just playing around, i've tried this and I got a totally different result from what I expected, then i've researched and i've seen that c++ takes already care when you add +1 to a pointer (it sums 4 bytes in this case).
Any idea?
For a pointer p to a type T with value v, the expression p+n will (on most systems anyway) result in a pointer to the address v+n*sizeof(T). To get a fixed-byte offset to the pointer, you can first cast it to a character pointer, like this:
reinterpret_cast<T*>(reinterpret_cast<char*>(p) + n)
In c++, sizeof(char) is defined to be equal to 1.
Do note that accessing improperly aligned values can have large performance penalties.
Another thing to note is that, in general, casting pointers to different types is not allowed (called the strict aliasing rule), but an exception is explicitly made for casting any pointer type to char* and back.
The trick is convert the type of array into any pointer-type with a size of 1 Byte, or store the pointer value in an integer.
#include <stdint.h>
int* increment_1(int* ptr) {
//C-Style
return (int*)(((char*)ptr) + 4);
}
int* increment_2(int* ptr) {
//C++-Style
char* result = reinterpret_cast<char*>(ptr);
result += 4;
return reinterpret_cast<int*>(result);
}
int* increment_3(int* ptr) {
//Store in integer
intptr_t result = reinterpret_cast<intptr_t>(ptr);
result += 4;
return reinterpret_cast<int*>(result);
}
Consider that if you add an arbitrary number of bytes to an address of an object of type T, it no longer makes sense to use a pointer of type T, since there might not be an object of type T at the incremented memory address.
If you want to access a particular byte of an object, you can do so using a pointer to a char, unsigned char or std::byte. Such objects are the size of a byte, so incrementing behaves just as you would like. Furthermore, while rules of C++ disallow accessing objects using incompatible pointers, these three types are excempt of that rule and are allowed to access objects of any type.
So, given
int * array = ....
You can access the byte at index 4 like this:
auto ptr = reinterpret_cast<unsigned char*>(array);
auto byte_at_index_4 = ptr + 4;
array + 0x004
If im correct this will lead to add 4*4 (16) bytes
Assuming sizeof(int) happens to be 4, then yes. But size of int is not guaranteed to be 4.
Here is the problem program:
#include <stdio.h>
int main()
{
int apricot[2][3][5];
int (*r)[5]=apricot[0];
int *t=apricot[0][0];
printf("%p\n%p\n%p\n%p\n",r,r+1,t,t+1);
}
The output of it is:
# ./a.out
0xbfa44000
0xbfa44014
0xbfa44000
0xbfa44004
I think t's dimension's value should be 5 because t is the last dimension,and the fact is matched(0xbfa44004-0xbfa44000+1=5)
But the r's dimension's value is 0xbfa44014-0xbfa44000+1=21,I think it should be 3*5=15,because 3 and 5 are the last two dimensions,then why the difference is 21?
r is a pointer to an array of 5 ints.
Assuming 1 int is 4 bytes on your system (from t and t+1), then "stepping" that pointer by 1 (r+1) means an increase in 5*4 = 20 bytes. Which is what you get here.
You get tricked by the C syntax. r is an array pointer to an array of int, t is a plain int pointer. When doing any kind of pointer arithmetic, you do it in the unit pointed at.
Thus t+1 means the address of t + the size of one pointed-at object. Since t points at int and int is 4 bytes on your system, you get an address 4 bytes from t.
The same rule applies to r. It is a pointer to an array of 5 int. When you do pointer arithmetic on it by r+1, you get the size of the pointed-at object, which has size 5*sizeof(int), which happens to be 20 bytes on your computer. So therefore r+1 gives you an address 20 bytes (==14 hex) from r.
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Question about pointer increment
When i increment a int pointer then its address have a gap of 4 bytes. why it is so ? why a int pointer takes 4 bytes to store whereas a char takes 2 bytes ?
When you increment a pointer of a type A, you move that pointer forward in the memory by the size of the type it points to. On your machine, int takes 4 bytes, so the pointer moves by 4 bytes.
As for "why does int take 4 bytes on my machine?":
The C++ standard says (4.9.1. paragraph 2):
There are five standard signed integer types : “signed char”, “short
int”, “int”, “long int”, and “long long int”. In this list, each type
provides at least as much storage as those preceding it in the list.
<...> Plain ints have the natural size suggested by the architecture
of the execution environment[44]; the other signed integer types are
provided to meet special needs.
[44]: that is, large enough to contain any value in the
range of INT_MIN and INT_MAX, as defined in the header .
Basically, the sizes of fundamental types are not set in stone, and are implementation-defined. The accepted answer to this SO question has some information about it.
Here is the general rule:
If the type is T, its size N is calculated as sizeof(T) bytes. So pointer of type T* is increased by N bytes if you increment the pointer by 1.
Mathematically,
T *p = getT();
size_t diff = static_cast<size_t>(p+1) - static_cast<size_t>(p);
bool alwaysTrue = (diff == sizeof(T)); //alwaysTrue is always true!
the size of the pointer to any data types always be the same as supported by your system
If system is 32 -bit the size would be 4 bytes for all the pointers.
In pointer arithmetic when you do ptr++ or ptr-- the increments and decrements takes place according to the size of the data type this ptrpointer points to .
char *cptr;
int *iptr;
char c[5];
int a[5];
cptr=c;
iptr=a;
By doing cptr++ you will get c[1] and pointer will increments by only one byte
You can check the address of each char.
Similarly iptr++ will give you a[1] here pointer increased by 4 bytes.
int main()
{
int i;
for(i=0;i<5;i++)
{
printf("%p\t",&c[i]); //internally pointer arithmeitc: (c+sizeof(char)*i) ,
printf("%p\n",&a[i]); //intenally pointer arithmetic : (a+sizeof(int)*i)
}
}
Size of int or other data types are implementation defined
Pointers increment by the size in bytes of the things they point to. ints take 4 bytes on a 32-bit machine.
Because, on your computer, sizeof (int) == 4, so stepping from one int to the next requires an increment of four bytes.
Most integer types have different sizes on different computers. int must have at least 16 bits, and is supposed to be a "natural" size for the computer. Most 32 or 64-bit platforms choose 32 bits as a "natural" size, and most computers have 8-bit bytes, so 4 bytes is a very common size for int.
However, sizeof (char) == 1 on all computers, so I'm rather surprised that you say "a char takes 2 bytes". It should only take one.
because the size of data (int) which the pointer is pointing has 4 byte size so the pointer increments 4 bytes (size of data (int))
another example: if you have structure with size 8 byte and you have pointer pointing to this structure the increment of this pointer will be 8 byte:
struct test {
int x;
int y;
}
struct test ARRAY[50];
struct test *p=ARRAY; // p pointer is pointing here to the first element ARRAY[0]. ARRAY[0] is with size 8 bytes
p++; // this will increment p with 8 byte (size of struct test). So p now is pointing to the second element ARRAY[1]
Value of a pointer is address of a variable. Why value of an int pointer increased by 4-bytes after the int pointer increased by 1.
In my opinion, I think value of pointer(address of variable) only increase by 1-byte after pointer increment.
Test code:
int a = 1, *ptr;
ptr = &a;
printf("%p\n", ptr);
ptr++;
printf("%p\n", ptr);
Expected output:
0xBF8D63B8
0xBF8D63B9
Actually output:
0xBF8D63B8
0xBF8D63BC
EDIT:
Another question - How to visit the 4 bytes an int occupies one by one?
When you increment a T*, it moves sizeof(T) bytes.† This is because it doesn't make sense to move any other value: if I'm pointing at an int that's 4 bytes in size, for example, what would incrementing less than 4 leave me with? A partial int mixed with some other data: nonsensical.
Consider this in memory:
[↓ ]
[...|0 1 2 3|0 1 2 3|...]
[...|int |int |...]
Which makes more sense when I increment that pointer? This:
[↓ ]
[...|0 1 2 3|0 1 2 3|...]
[...|int |int |...]
Or this:
[↓ ]
[...|0 1 2 3|0 1 2 3|...]
[...|int |int |...]
The last doesn't actually point an any sort of int. (Technically, then, using that pointer is UB.)
If you really want to move one byte, increment a char*: the size of of char is always one:
int i = 0;
int* p = &i;
char* c = (char*)p;
char x = c[1]; // one byte into an int
†A corollary of this is that you cannot increment void*, because void is an incomplete type.
Pointers are increased by the size of the type they point to, if the pointer points to char, pointer++ will increment pointer by 1, if it points to a 1234 bytes struct, pointer++ will increment the pointer by 1234.
This may be confusing first time you meet it, but actually it make a lot of sense, this is not a special processor feature, but the compiler calculates it during compilation, so when you write pointer+1 the compiler compiles it as pointer + sizeof(*pointer)
As you said, an int pointer points to an int. An int usually takes up 4 bytes and therefore, when you increment the pointer, it points to the "next" int in the memory - i.e., increased by 4 bytes. It acts this way for any size of type. If you have a pointer to type A, then incrementing a A* it will increment by sizeof(A).
Think about it - if you only increment the pointer by 1 byte, than it will point to a middle of an int and I can't think of an opportunity where this is desired.
This behavior is very comfortable when iterating over an array, for example.
The idea is that after incrementing, the pointer points to the next int in memory. Since ints are 4 bytes wide, it is incremented by 4 bytes. In general, a pointer to type T will increment by sizeof(T)
A pointer points at the BEGINNING of something in memory. An INT occupies 4 bytes (32bit) and a DOUBLE occupies 8 bytes (64bit) in memory. So if you have a DOUBLE number stored, and you wish at a very low level pointing to the next available memory location, the pointer wooud be increased by 8 bytes. If for some reason you pointed at +4bytes from the start of a DOUBLE value, you would corrupt it's value. Memory is a very large flat field that has no conscience of itself, so it's up to the software to divides it properly and to "respect the borders" of items located in that field.