Reputation: 57
So while studying for my exams I was trying to do a practice problem for pointers.
In the following code I'm trying to display the number of elements before the first occurrence of 0.
There is only one part that i didn't understand please see the 6th last line.
#include <iostream>
using namespace std;
int main()
{
int A[10];
for (int i = 0; i < 10; i++){
cout << "Please enter number " << i + 1 << " in the array: ";
cin >> A[i];
}
int *Aptr = A;
while(*Aptr !=0){
cout << *Aptr << "";
Aptr++;
}
cout << "\nThere are " << (Aptr - A) //Here is what i don't understand.
<< " numbers before the first occurrence of 0." << endl;
system("pause");
return 0;
}
So why exactly is (Aptr - A) giving me the number of elements instead of a memory location, and why is this even doable since Aptr is a pointer and A is an array?
Can someone explain to me in detail?
Upvotes: 0
Views: 1438
Reputation: 6407
First of all, name of array A
is associated to address of (pointer at) the first item in the array.
So why exactly is (Aptr - A) giving me the number of elements?
Because according to rules address arithmetic subtraction operation (also +
, and similar) is performed based on the data type.
I mean, that compiler operating with int*
makes ++
, --
, addition, subtraction an integer, etc. adds addresses needed for shifting to next/previous item.
If you really want to see how many bytes are located between addresses, just convert addresses to int
before making subtraction:
cout << endl << "Address difference is " << int(Aptr) - int(A) << endl;
You can try that with different data types as follows:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int A[5];
short B[5];
unsigned char C[5];
cout << "Array (data type) | Syze of array | Size of item | Item distanse | Bytes distance" << endl;
cout << "A (int) :" << setw(10)
<< sizeof(A) << setw(15)
<< sizeof(A[0]) << setw(15)
<< &A[4] - A << setw(15)
<< int(&A[4]) - int(A) << endl;
cout << "B (short) :" << setw(10)
<< sizeof(B) << setw(15)
<< sizeof(B[0]) << setw(15)
<< &B[4] - B << setw(15)
<< int(&B[4]) - int(B) << endl;
cout << "C (un.char) :" << setw(10)
<< sizeof(C) << setw(15)
<< sizeof(C[0]) << setw(15)
<< &C[4] - C << setw(15)
<< int(&C[4]) - int(C) << endl;
system("pause");
return 0;
}
UPDATE
To be better prepared for your exam, consider the following example with pointers:
#include <iostream>
using namespace std;
int main()
{
int A[5] = {0}; // all items now are 0
int * P = A + 2; // the same as P = &A[2];
*P = 33; // writing to item A[2];
cout << A[2] << endl; // just to check in usual way
cout << *(A + 2) << endl; // using A as a pointer
cout << *(2 + A) << endl; // almost the same to previous
cout << 2[A] << endl; // quite strange, but it works
cout << 0[P] << endl; // and this is the same
return 0;
}
You must understand that 0[P]
means for compiler *(0 + P)
, as well as 2[A]
means - *(2 + A)
, but you should not write in your program in such style (exceptions are only cases when you want to confuse a reader).
And one more important thing - difference between array and pointer - are shown in the following example:
int A[] = {1, 2, 3, 4, 5};
int *P = A;
cout << "A = " << A << endl;
cout << "P = " << P << endl;
cout << "size of A = " << sizeof(A) << endl;
cout << "size of P = " << sizeof(P) << endl;
even if the addresses (vaules A and P) are equal, compiler works with array (A
) in a different way than with pointer: sizeof(A)
means memory allocated for whole array (5 items of sizeof(int)
each), but sizeof(P)
means memory allocated for data type int *
(pointer to int). So, sizeof(P)
depends only on compiler and OS platform (e.g. pointer can be 32-bit or 64-bit), but sizeof(A)
depends on size of item (int
may be not 32 bits) and NUMBER OF ITEMS in the array.
And you can "go to the next item" with pointer:
P++;
cout << *P << endl;
but you are not able to do:
A++;
because A
is not variable of pointer type (it is just similar in sense of "address of the first item"), and compiler will say you something like:
error : '++' needs l-value
Upvotes: 1
Reputation: 36597
When used in an expression, like Aptr - A
, the name of an array A
will be implicitly converted to a pointer (equal to &A[0]
).
Then the compiler is faced with subtracting two pointers of the same type (both of type int *
in your case). That is specified as giving a value of type std::ptrdiff_t
, which is, in turn "a signed integral type able to represent the result of subtracting two pointers".
Pointer arithmetic, when subtracting two pointers of type int
(i.e. two int *
s) gives the number of int
s between the two pointers (assuming they are in the same object, which is true in this case, since Aptr
points at an element of the array A
).
Practically, if Aptr
is equal to &A[i]
, the subtraction Aptr - &A[0]
gives a std::ptrdiff_t
equal to i
.
Note: there is another problem in your code, as since the first (for
) loop reads 10
values, while the second while
loop keeps incrementing Aptr
until it points at an int
with value 0
. If the user enters any zero values, the second loop will stop when it finds the first (even if the user enters non-zero elements after that). If the user enters no values equal to 0
, then the while
loop has undefined behaviour, since Aptr
will keep walking through memory past the end of A
until it happens to find memory that compares (as an int
) equal to 0
.
Upvotes: 4