数组和指针使算术混乱

Arrays and pointers arithmetic confusion

本文关键字:混乱 指针 数组      更新时间:2023-10-16
#include <iostream>
using namespace std;
int main ()
{
int numbers[5];
int * p;
p = numbers;  *p = 10;
p++;  *p = 20;
p = &numbers[2];  *p = 30;
p = numbers + 3;  *p = 40;
p = numbers;  *(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
return 0;
}

这里有相当新的编码器。这是取自cplusplus.com上的指针页面的示例。他们谈论取消引用,运算符的地址,然后他们谈论数组和指针之间的关系。我注意到如果我简单地打印出一个声明的数组,它会吐出数组的地址。我真的在试图确切地理解其中一些代码行在做什么,并且遇到了困难。

一切都有意义,直到*p=10.我把它理解为,"指针 p 指向的值等于 10",但array不仅仅是一个值。在这种情况下,它是 5...那么,这是怎么回事呢?编译器会假设我们正在谈论数组的第一个元素吗?

更让我困惑的是p++;. 现在p是数组的地址。当 p 是地址时,你怎么p=p+1

我明白p= &numbers[2];.以及以下*p = 30;.

p = numbers + 3;让我感到困惑。为什么我们可以获取一个地址并向其添加3?而且,这甚至意味着什么?

for 循环中的所有内容都是有意义的。只是打印出数组正确吗?

提前感谢您的帮助!

正如指出的那样,由于指针算术。 所以数组numbers和指针p都是int的,所以在将numbers的基址分配给指针p并且*p=10numbers[0]=10

现在,当您执行 p++ 时,p 的地址会递增,但不会像++的正常算术运算那样递增到下一个数值,而是递增到下一个索引的地址numbers

假设一个 int 是 4 字节的内存,numbers的初始地址是 1000。 因此,p++使地址增加到1004,这是numbers[1]基本上它指向内存中的下一个 int 变量位置。因此,当遇到*p = 20时,值 20 将被分配给下一个相邻内存,即 1004 或numbers[1]=20

之后,p直接分配了第 3 个索引的地址numbers[2]即 1008(内存中的下一个 int var)。现在p指向numbers的第三个指数,所以*p=30再次numbers[2]=30

p = numbers + 3; *p = 40;做类似的事情,即将数字的基址分配给 3 个索引(1000 + 3*sizeof(int) =1012 ==>1000 + 3*4 =1012)到p并为此分配 40。 所以它变得等同于numbers[3]=40.

然后p = numbers; *(p+4) = 50;将 1000 分配给p,并使用()4添加到p的地址,并使用*()将 50 分配给该值,该值是大括号内地址的值(1000+ 4*4 = 1016)。

在 C++: 中使用这样的指针:p = numbers使 p 指向数组的第一个元素。因此,当你做p++p你是在指向第二个元素。

现在,执行*p = 1010分配给p指向的任何内容,就像在您的情况下p指向数组的第一个元素一样,则*p = 10numbers[0] = 10相同。

如果你以后看到这个:*(p + i) = 20,这是指针算术,与p[i] = 20相同。这就是为什么p[0] = 10等同于*(p + 0) = 10,等同于*p = 10

关于您的问题:How do you do p=p+1 when p is an address?:由于C++中的数组按顺序存储在内存中,如果元素p指向内存地址6400010p++指向6400014假设每个元素指向p占用 4 个字节。如果你想知道为什么p++6400014而不是6400011,原因是C++有点神奇:当增加指针时,它不会增加1 byte而是增加1 element所以如果你指向整数,每个整数都占据4 bytes,那么p将增加4而不是1

让我们分解一下:

int numbers[5];
int * p;

将数组变量分配给指针意味着指针将指向第一个元素:

p = numbers;      // p points to the 1st element
*p = 10;          // 1st element will be 10
p++;              // go to next location i.e. 2nd element
*p = 20;          // 2nd element will be 20

您可以进行指针算术,它根据类型工作。递增32-bit计算机上的int指针将在内存中跳转4个字节。在64-bit计算机上,这将是8字节。请记住,不能使用void指针执行此操作。

p = &numbers[2];   // assign the address of 3rd element
*p = 30;           // 3rd element will be 30
p = numbers + 3;   // numbers + 3 means the address of 4th element
*p = 40;           // 4th element will be 40
p = numbers;       // p points to the 1st element
*(p + 4) = 50;     // p + 4 means the address of 5th element
// dereference 5th location and assign 50
// 5th element will be 50

网络上有很多关于指针如何工作的页面。但有几件事需要快速指出。

int* p;

上面的行表示 p 是指向 int 的指针。 为其分配某些内容不会改变它是什么。它是指向 int 的指针,而不是 int 数组。

int number[5];
p = number;

此赋值采用存储数组的地址,并将其分配给 p.p 现在指向该数组的开头。

p++;

p 现在指向数组中的第二个整数。指针按指针指向的对象的大小递增。因此,实际地址可能会增加 4 或 8,但它会转到 int 的下一个地址。

*p = 30;

这是一个作业,而不是比较。它并没有说 p 指向的是 30,而是将 30 复制到 p 指向的地址中。说"等于"在编程术语中通常令人困惑,因此使用"分配"或"比较"以明确。

1>p=numbers;
指针p现在指向数组的开头,即第一个元素。

2>*p=10;
第一个元素现在变成 10,因为p指向第一个元素。

3>p++;
这会将指针移动到数组的下一个元素,即第二个元素
因此,*p=20;再次second element=20

4>p = &numbers[2];
此语句意味着p现在指向数组的第 3 个元素。
因此,*p = 30;3rd element=30

5>p = numbers + 3;
Wen 我们这样做p=numbers+1;它指向第二个元素,所以p=numbers+3;现在将指向数组的第 4 个元素。*p = 40;使fourth element=40

6>p = numbers;
再次p指向数组
的第一个元素*(p+4) = 50;现在将产生5th element=50