[英]The number of elements in an array using pointers in C++
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. 在以下代码中,我尝试显示首次出现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? 那么,为什么(Aptr-A)确切地给了我元素个数而不是内存位置,又为什么因为Aptr是一个指针而A是一个数组,这甚至可行呢?
Can someone explain to me in detail? 有人可以详细向我解释吗?
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]
). 当在表达式(如
Aptr - A
,数组A
的名称将隐式转换为指针(等于&A[0]
)。
Then the compiler is faced with subtracting two pointers of the same type (both of type int *
in your case). 然后,编译器将要减去两个相同类型的指针(在您的情况下均为
int *
类型)。 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". 这被指定为给出类型为
std::ptrdiff_t
的值,该值又是“一个有符号的整数类型,能够表示减去两个指针的结果”。
Pointer arithmetic, when subtracting two pointers of type int
(ie 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
). 指针算术,当减去两个类型为
int
指针(即两个int *
s)时,将得出两个指针之间的int
数(假设它们在同一个对象中,在这种情况下是正确的,因为Aptr
指向的元素为数组A
)。
Practically, if Aptr
is equal to &A[i]
, the subtraction Aptr - &A[0]
gives a std::ptrdiff_t
equal to i
. 实际上,如果
Aptr
等于&A[i]
,则减法Aptr - &A[0]
给出等于i
的std::ptrdiff_t
。
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
. 注意:您的代码中还有另一个问题,因为第一个(
for
)循环读取10
值,而第二个while
循环保持Aptr
递增,直到它指向值为0
的int
为止。 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
. 如果用户没有输入任何等于
0
值,则while
循环具有未定义的行为,因为Aptr
将继续遍历A
末尾的内存,直到碰巧找到比较(等于int
)等于0
内存。
First of all, name of array A
is associated to address of (pointer at) the first item in the array. 首先,数组
A
名称与数组中第一项的地址(指针指向)相关联。
So why exactly is (Aptr - A) giving me the number of elements?
那么,为什么(Aptr-A)确实给了我元素个数呢?
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. 我的意思是,使用
int*
进行操作的编译器使++
, --
,加法,减法成为整数等,从而添加了移至下一个/上一个项目所需的地址。
If you really want to see how many bytes are located between addresses, just convert addresses to int
before making subtraction: 如果您真的想查看地址之间有多少字节,只需在进行减法之前将地址转换为
int
:
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). 您必须了解
0[P]
表示编译器*(0 + P)
,以及2[A]
表示- *(2 + A)
,但您不应以这种方式编写程序(例外情况是例外当您想使读者感到困惑时)。
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). 即使地址(值A和P)相等,编译器对数组(
A
)的处理方式也与指针不同: sizeof(A)
表示为整个数组分配内存sizeof(int)
每个5项sizeof(int)
),但是sizeof(P)
表示分配给数据类型int *
(指向int的指针sizeof(P)
内存。 So, sizeof(P)
depends only on compiler and OS platform (eg 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. 因此,
sizeof(P)
仅取决于编译器和OS平台(例如,指针可以是32位或64位),但是sizeof(A)
取决于项目的大小( int
可能不是32位)和数组。
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: 因为
A
不是指针类型的变量(就“第一项的地址”而言,它是相似的),并且编译器会说:
error : '++' needs l-value
错误:“ ++”需要左值
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.