使用C ++

时间:2016-12-16 05:48:17

标签: c++ arrays pointers

因此,在为我的考试学习时,我试图为指针做练习问题。

在下面的代码中,我尝试显示第一次出现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 是一个数组?

有人能详细向我解释一下吗?

2 个答案:

答案 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值