数组和指针算术混淆

时间:2017-07-22 06:01:36

标签: c++ pointers pointer-arithmetic

#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之前,一切都有意义。我读这个,&#34;指针p指向的值等于10&#34;但array不是一个值。在这种情况下它是5 ...所以,这笔交易是什么?编译器会假设我们正在讨论数组的第一个元素吗?

对我来说更令人困惑的是p++;p现在是数组的地址。当p是地址时,你如何做p=p+1

我理解p= &numbers[2];。以及以下*p = 30;

p = numbers + 3;让我困惑。为什么我们能够获取地址并只添加3?而且,这甚至意味着什么?

for循环中的所有内容都有意义。它只是正确地打印出阵列吗?

提前感谢您的帮助!

5 个答案:

答案 0 :(得分:2)

由于指针算法指出这一点。 因此,数组numbers和指针p都是int,因此在将numbers的基址分配给指针p并且*p=10执行{{{ 1}}

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

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

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

numbers[2]=30做类似的事情是将数字的基地址增加3个索引(1000 + 3 * sizeof(int)= 1012 ==&gt; 1000 + 3 * 4 = 1012)到{{1}并指定40。所以它等同于p = numbers + 3; *p = 40;

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

答案 1 :(得分:1)

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

现在,*p = 1010分配给p指向的任何内容,就像您的情况p指向数组的第一个元素一样,然后*p = 10 1}}与numbers[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指向内存地址6400010,则p++指向6400014假设p指向的每个元素占用4个字节。如果你想知道为什么p++而不是6400014而不是6400011,原因是C ++有点神奇:当增加指针时,它不会增加1 byte但是增加1 element因此,如果您指向整数,则每个占据4 bytes,然后p将增加4而不是1

答案 2 :(得分: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

你可以做指针运算,它可以根据类型工作。在int计算机上递增32-bit指针将在内存中跳转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

答案 3 :(得分:0)

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

int* p;

上面的行意味着p是指向int的指针。为其分配内容并不会改变它的含义。它是指向int的指针,而不是int的数组。

int number[5];
p = number;

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

p++;

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

*p = 30;

这是一项任务,而非比较。它没有说p指向的是30,它将30复制到p指向的地址。说“等于”在编程术语中通常会令人困惑,因此使用“assign”或“compare”来清楚。

答案 4 :(得分:0)

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

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

3&gt; p++;
   这会将指针移动到数组的下一个元素,即第二个元素
   因此,再次*p=20;second element=20作为p = &numbers[2]; 4&gt; p
   这个陈述意味着*p = 30;现在指向数组的第3个元素    因此,3rd element=30p = numbers + 3;作为p=numbers+1; 5&gt; p=numbers+3;
   我们*p = 40;它指向第二个元素,所以fourth element=40现在将指向数组的第四个元素。 p = numbers;制作p

6&gt; *(p+4) = 50;
   再次5th element=50指向数组的第一个元素    ... /** Section: Global Variables Definitions */ void (*TMR2_InterruptHandler)(void); ... /** Section: TMR2 APIs */ void TMR2_Initialize(void) { // Set TMR2 to the options selected in the User Interface // T2CKPS 1:2; T2OUTPS 1:2; TMR2ON off; T2CON = 0x11; // T2CS LFINTOSC; T2CLKCON = 0x04; // T2PSYNC Not Synchronized; T2MODE Software control One shot; T2CKPOL Rising Edge; T2CKSYNC Not Synchronized; T2HLT = 0x08; // T2RSEL TMR4_postscaled; T2RST = 0x02; // PR2 8; T2PR = 0x08; // TMR2 0; T2TMR = 0x00; // Clearing IF flag before enabling the interrupt. PIR4bits.TMR2IF = 0; // Enabling TMR2 interrupt. PIE4bits.TMR2IE = 1; // Set Default Interrupt Handler TMR2_SetInterruptHandler(TMR2_DefaultInterruptHandler); // Start TMR2 TMR2_Start(); } void TMR2_ISR(void) { // clear the TMR2 interrupt flag PIR4bits.TMR2IF = 0; if(TMR2_InterruptHandler) { TMR2_InterruptHandler(); } } void TMR2_SetInterruptHandler(void* InterruptHandler) { TMR2_InterruptHandler = InterruptHandler; } void TMR2_DefaultInterruptHandler(void) { // add your TMR2 interrupt custom code // or set custom function using TMR2_SetInterruptHandler() } /** End of File */ 现在将wrapper.getVariable( "Efficiency" ).value = excel.range("'Cases'!$H$21") wrapper.getVariable( "Plant_Price" ).value = excel.range("'Cases'!$H$328") wrapper.getVariable( "Plant_Price_PerKW" ).value = excel.range("'Cases'!$H$331") wrapper.getVariable( "Net_Present_Value" ).value = excel.range("'Cases'!$H$782")