我是一个新手试图理解双指针的工作和打印双指针。我将m
递增1,但它始终指向p
指向的最后一个值。有人可以帮助我吗?
#include <stdio.h>
int main () {
/* an array with 5 elements */
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double *p;
double **m;
int i;
p = balance;
m = &p;
/* output each array element's value */
printf( "Array values using pointer\n");
for ( i = 0; i < 5; i++ ) {
printf("*(p + %d) : %f\n", i, *(p+i) );
}
for ( i = 0; i < 5; i++ ) {
printf("**(m + %d) : %f\n", i, *m);
m++;
}
printf( "Array values using balance as address\n");
for ( i = 0; i < 5; i++ ) {
printf("*(balance + %d) : %f\n", i, *(balance + i) );
}
return 0;
}
答案 0 :(得分:1)
您的数组balance
就像这样
+--------+--------+--------+--------+--------+ | 1000.0 | 2.0 | 3.4 | 17.0 | 50.0 | +--------+--------+--------+--------+--------+
初始化p
和m
之后,就像这样:
+---+ | m | +---+ | v +---+ | p | +---+ | V +--------+--------+--------+--------+--------+ | 1000.0 | 2.0 | 3.4 | 17.0 | 50.0 | +--------+--------+--------+--------+--------+
也就是说,m
指向p
的位置,p
指向balance
数组的第一个值。
当您取消引用m
时(即当您执行*m
时),您将获得m
所指向的值。此值是另一个指针(p
),您需要取消引用才能访问数组中的元素。
使用m
balance
中的第二个元素(即balance[1]
)为(*m)[1]
。
现在,如果您增加m
(例如m++
),它将指向p
的下一个元素:
+---+ | m | +---+ | v +---+ | p | +---+ | V +--------+--------+--------+--------+--------+ | 1000.0 | 2.0 | 3.4 | 17.0 | 50.0 | +--------+--------+--------+--------+--------+
您可以在此处清楚地看到问题:它不再指向p
,您再也无法使用它来访问balance
数组。在增量之后取消引用m
将导致未定义的行为。
此外,对于任何指针或数组,数组索引表达式和指针算术表达式是相等的。因此,对于balance
,表达式balance[i]
等于*(balance + i)
。它们之间确实没有区别。
答案 1 :(得分:0)
执行
之后double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double *p;
double **m;
p = balance;
m = &p;
以下都是真的:
m == &p // double **
*m == p == &balance[0] // double *
**m == *p == balance[0] // double
(*m)[i] == p[i] == balance[i] // double
请记住表达式a[i]
定义为*(a + i)
;给定地址a
,偏移i
元素(不是字节 1 )并取消引用结果。
这意味着*p
相当于*(p + 0)
,相当于p[0]
。因此,您可以使用p[i]
代替balance[i]
。自*m == p
起,您也可以使用(*m)[i]
代替p[i]
。括号是必要的 - 一元*
的优先级低于后缀[]
,因此*m[i]
将被解析为*(m[i])
,这不是您想要的。
您可以直接将p
增加到“走遍”balance
数组:
p = balance; // p == &balance[0];
for ( i = 0; i < 5; i++ )
printf( "%f\n", *p++ );
每次循环时,p
都会递增以指向balance
的下一个元素。
您可以使用表达式(*m)
执行类似的操作:
p = balance; // p == &balance[0]
m = &p;
for ( i = 0; i < 5; i++ )
printf( "%f\n", (*m)++ );
同样,*m
周围的括号是必要的;由于postfix ++
的优先级高于一元*
,因此表达式*m++
将被解析为*(m++)
,这不是我们想要的。我们不想更改m
的值,我们希望更改m
指向的值,在本例中为p
。
现在,假设我们完全离开了p
;我们可以这样做:
double balance[5] = { ... };
double **m;
*m = balance;
没有。在此示例中,m
是无效指针;它尚未初始化为指向任何有意义的位置,因此*m
将调用未定义的行为(可包括但不限于段错误)。 m
指向double *
类型的对象,然后才能取消引用它。必须有像p
这样的中间人才能使该计划奏效。
<小时/>
a
指向类型为T
的对象,则a + 1
将生成下一个对象的地址键入T
,它可能比当前地址多1个字节。