因此,在为我的考试学习时,我试图为指针做练习问题。
在下面的代码中,我尝试显示第一次出现0之前的元素数量。
只有一部分我不明白,请参阅第6行最后一行。
#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 是一个数组?
有人能详细向我解释一下吗?
答案 0 :(得分:4)
在表达式中使用时,如Aptr - A
,数组A
的名称将被隐式转换为指针(等于&A[0]
)。
然后编译器面临减去相同类型的两个指针(在你的情况下都是类型int *
)。这被指定为给出std::ptrdiff_t
类型的值,这反过来又是#34;一个有符号的整数类型,能够表示减去两个指针的结果&#34;。
指针算法,当减去两个类型为int
的指针(即两个int *
s)时,会给出两个指针之间的int
个数(假设它们在同一个对象中,在这种情况下是正确的,因为Aptr
指向数组A
的元素。)
实际上,如果Aptr
等于&A[i]
,则减法Aptr - &A[0]
会使std::ptrdiff_t
等于i
。
注意:您的代码中存在另一个问题,因为第一个(for
)循环读取10
值,而第二个while
循环继续递增Aptr
直到它指向int
,其值为0
。如果用户输入任何零值,则第二个循环将在找到第一个循环时停止(即使用户在此之后输入非零元素)。如果用户未输入等于0
的值,则while
循环具有未定义的行为,因为Aptr
将在A
结束后继续遍历内存,直到它发生找到比较(int
)等于0
的内存。
答案 1 :(得分:1)
首先,数组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)
仅依赖于编译器和OS平台(例如,指针可以是32位或64位),但sizeof(A)
取决于项的大小(int
可能不是32位)和数组中的项目数。
你可以用指针“转到下一个项目”:
P++;
cout << *P << endl;
但你无法做到:
A++;
因为A
不是指针类型的变量(它在“第一项的地址”方面类似),编译器会说你这样的东西:
错误:'++'需要l值