数组中使用指针的元素数 C++

The number of elements in an array using pointers in C++

本文关键字:元素 C++ 指针 数组      更新时间:2023-10-16

所以在为考试做准备时,我试图为指针做一道练习题。

在下面的代码中,我尝试显示第一次出现 0 之前的元素数。

只有一部分我不明白,请看倒数第六行。

#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;
}

那么为什么 (Aptr - A)给我元素的数量而不是内存位置,为什么这甚至是可行的,因为Aptr是一个指针而A是一个数组?

有人可以详细解释一下吗?

当在表达式中使用时,如Aptr - A,数组A的名称将被隐式转换为指针(等于&A[0])。

然后编译器面临减去两个相同类型的指针(在您的情况下都是int *类型)。 这被指定为给出一个类型为std::ptrdiff_t的值,而该值又是"一个能够表示减去两个指针的结果的有符号整数类型"。

指针算术,当减去两个类型为int的指针(即两个int *s)时,给出两个指针之间的ints 数(假设它们在同一个对象中,在这种情况下是正确的,因为Aptr指向数组的一个元素A)。

实际上,如果Aptr等于&A[i],减法Aptr - &A[0]给出的std::ptrdiff_t等于i

注意:您的代码中还有另一个问题,因为第一个(for)循环读取10值,而第二个while循环不断递增Aptr,直到它指向值为0int。 如果用户输入任何零值,则第二个循环将在找到第一个时停止(即使用户在此之后输入非零元素)。 如果用户输入的值不等于0,则while循环具有未定义的行为,因为Aptr将在A结束时继续遍历内存,直到碰巧找到比较(作为int)等于0的内存。

首先,数组A的名称与数组中第一项的地址(指针)相关联。

那么为什么(Aptr - A)给我元素的数量呢?

因为根据规则地址算术减法运算(也+,和类似)是基于数据类型执行的。

我的意思是,使用int*操作的编译器使++--、加法、减法等添加移动到下一个/上一项所需的地址。

如果您真的想查看地址之间有多少字节,只需在减法之前将地址转换为int

cout << endl << "Address difference is " << int(Aptr) - int(A) << endl;

您可以尝试使用不同的数据类型,如下所示:

#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;
}

更新

为了更好地准备考试,请考虑以下带有指针的示例:

#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;
}

你必须明白0[P]编译器*(0 + P)的意思,以及2[A]意味着 -*(2 + A),但你不应该以这种风格编写程序(例外情况只是你想混淆读者的情况)。

还有一个更重要的事情 - 数组和指针之间的区别 - 如以下示例所示:

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;

即使地址(vaules A 和 P)相等,编译器处理数组 (A) 的方式也与使用指针的方式不同:sizeof(A)表示为整个数组分配的内存(每个 5 项sizeof(int)项),但sizeof(P)表示为数据类型int *分配的内存(指向 int 的指针)。因此,sizeof(P)仅取决于编译器和操作系统平台(例如指针可以是 32 位或 64 位),但sizeof(A)取决于项目的大小(int可能不是 32 位)和数组中的项目数。

您可以使用指针"转到下一项":

P++;
cout << *P << endl;

但你做不到:

A++;

因为A不是指针类型的变量(它只是在"第一项的地址"的意义上相似),编译器会这样说你:

错误:"++"需要 L 值