C Pointers with 2D arrays [duplicate] - c++

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.

Related

Query related to pointers [duplicate]

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.

when ever i tried to check the size of pointer variable i.e, int *p sizeof(p) then always give 8 bit. Why?

When I declared an integer array of size 10 and check the size it gives 40 but when I declared integer pointer variable with an array of size 10 and I try to check the size it always gives 8. Why?
int A[10];
cout<<sizeof(A)<<endl; // it gives 40;
int *p;
p = new int[10];
cout<<sizeof(*p)<<endl; // but it gives always 8;
sizeof(p) is always going to be sizeof(int*), which is 8 on your platform.
That does not change regardless of the number of objects you allocate using new [].
A is of type int [10] (an array of 10 ints). Its size is 10 * sizeof(int).
It makes sense that sizeof(A) is 40.
Pointers and arrays are different types. They can be used interchangeably in many use cases but it's also important to know how they are different and where they behave differently. sizeof operator is one of the use cases where they are different.
On a typical 64-bit machine, sizeof(*p) should be 4, while sizeof(p) should be 8.
Hopefully this example clears things up:
int p1[10];
cout<<sizeof(*p1)<<endl; // 4 size of the first element (int)
cout<<sizeof(p1)<<endl; // 40 size of array (int size * 10)
int *p2;
p2 = new int[10];
cout<<sizeof(*p2)<<endl; // 4 size of the first element (int)
cout<<sizeof(p2)<<endl; // 8 size of the pointer on 64-bit system
// shows how you're getting the first value by dereferencing
cout<<*p2<<endl; // 0
p2[0] = 100;
cout<<*p2<<endl; // 100
Always pointer holds the starting address of an array. Since it's an int pointer, and the size of the int in ur system is 8 bytes, it shows 8 bytes.

Pointers, Arrays and the new Operator

int (*ptr)[3]=new int [1][3];
I understand that int (*ptr)[3] creates a pointer to a 3-element integer-holding array.
I understand that new int [1][3] dynamically allocates some memory of size 1 row x 3 col x 4 bytes (32-bit machine) = 12 bytes.
I also understand that ptr [0] = &ptr [0] in this case.
The total memory allocated here is 3 * 12 bytes. Why?
Why is the 3 on the LHS dependent on the 3 on the RHS? If we use 3 on the RHS, we have to use 3 on the LHS. I cannot use 2 or 4.
Maybe it's a trivial logic, but I don't seem to find good literature on this.
First, the total memory allocated is not 3*12 bytes. It's
3*1*sizeof(int) + k bytes, where k is unspecified (but in
most implementations, will be 0 when allocating arrays of
int).
Second, the two 3 must be equal because they are part of the
type. On the left, the type is "pointer to 3 int". On the
right, you are allocating an "array of 1 array of 3 int";
because of the semantics of array new, the type of the
expression is point to array of 3 int (and any information
concerning whether it was int[1][3] or int[2][3] or whatever
has been lost). C++ uses static type checking (for the most
part), so the compiler must know all parts of the type at
compile time.
Given the information you have provided so far, I can only answer the second part of your question:
Why is the 3 on the LHS dependent on the 3 on the RHS?
int (*ptr)[3] // creates a pointer to an array of 3 ints
that means your variable ptr should point to an array of array of length threes only and when you are writing new int [1][3], you are essentially creating an array of length threes with one row(2-D array) only. Similarly new int [2][3] would give you an array of threes with two rows.(2-D array) That's why both of the threes are dependent on each other.

Why a pointer to an integer increments by 4 bytes? [duplicate]

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]

Why does int pointer '++' increment by 4 rather than 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.