1

请帮助我理解以下代码按其方式工作的原因:

#include <stdio.h>

int main(){
    int a = 10;
    void *b = &a;
    int *p = b; 
    printf("%u",*p++);
    return 0;
}

我知道 printf 的输出将是 10,但我不太明白为什么 *p++ 是 10

这是我的步骤:

1)void *b = &a;将 a 的地址存储在指针 b 中

2) int *p = b;指针 p 现在指向与指针 b 相同的数据项

3)printf("%u",*p++);是我感到困惑的地方......指针p的取消引用是a,即10......*p++与10 + 1基本不同,即11?

4

6 回答 6

3

*p++本质上是*(p++). 它计算为p增加之前的值,即 的地址a。然后你取消引用它,它评估为 value 10

于 2013-10-19T04:09:07.553 回答
2

为什么 *p++ 是 10 ?

[C11: §6.5.2.4/2]:后缀 ++ 运算符的结果是操作数的值。作为副作用,操作数对象的值会递增(即,将相应类型的值 1 添加到其中)。

下面的声明

printf("%u",*p++);

相当于

printf("%u",*p); /* p points to 'a' and value of `a` is 10. Hence, 10 is printed */
p = p + 1;  

p指向 int 类型的指针。因此,1缩放为sizeof (int)

结果, p 现在指向一个intat 地址:p + sizeof (int)

于 2013-10-19T05:27:23.687 回答
2

*p++被解析为*(p++)p++计算为p然后递增p,因此在下一次引用 之前不会看到更改p。所以*p是 10,*p++是 10(但 p 现在指向&a+1),*++p是未定义的行为(因为*(&a+1)不是有效值),(*p)++是 10 但更改a为 11,并且++*p(或++(*p))是 11(原样a)。

于 2013-10-19T04:15:17.517 回答
2

变量 p 是一个指向 int 的指针(指向 a)

表达式 *p 取消引用指针,因此它就像直接访问 int a 一样。

指针 p 上的运算符后缀 ++ 优先于取消引用。因此,*p++ 在计算表达式之后增加指针 p(到 int a 之后内存中的任何垃圾),因此取消引用仍然解析为 a,这就是打印 10 的原因。但在语句运行后,p 的值发生了变化。因此,如果您执行 printf("%u ",*p) ,很可能在该语句之后,您将获得一个尴尬的值。

但是,如果您执行 ++*p,则表达式被评估为对 p 指向的取消引用的 int 变量的 ++ 操作。如果你想避免这样的麻烦,当不确定时,使用括号:

(*p)++
++(*p)

而且您要确保您取消引用价值并采取行动。增加指针值是 C 和 C++ 等语言所允许的非常危险的操作,因此请尽可能避免!

于 2013-10-19T04:05:22.617 回答
2

表达式中的后自增运算符*p++适用于指针,而不是存储在该位置的值,因此在计算结果之前之后,结果永远不会是 11。该表达式的*p++意思是:取消引用p(获取它的值)然后增加p一个位置。由于p指向 a int,因此递增它将向前移动sizeof(int)字节。加法永远不适用于指向的值,p即 10。

但是,表达式 (*p)++ 不同。它取消对 p 的引用(获取它的值),然后递增该内存位置中的值。表达式计算为原始值。所以执行语句后

int c = (*p)++;

变量c将等于 10,而a将等于 11。

于 2013-10-19T04:07:23.323 回答
1

我只想加我的五分钱。
对于通过指针间接递增的值,您可以使用++*ipor (*ip)++。K&R 书中对括号有一个很好的解释:

在最后一个示例中,括号是必需的 (*ip)++;没有它们,它们的表达式将增加 ip 而不是它指向的内容,因为像 * 和 ++ 这样的一元运算符从右到左关联。

在您的代码中,您得到 10,因为 printf 将打印变量的原始值,并且仅在由于使用后缀++运算符而将其递增 1 之后。

于 2014-03-04T12:38:45.830 回答