请帮助我理解以下代码的工作原理:
#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;
存储指针b的地址
2)int *p = b;
指针p现在指向与指针b相同的数据项
3)printf("%u",*p++);
是我感到困惑的地方......指针p的取消引用是a,这是10 ...不是*p++
基本上与10 + 1相同,这将是11?
答案 0 :(得分:3)
*p++
基本上是*(p++)
。它会在p
递增之前评估a
的值,这是10
的地址。然后取消引用它,其值为{{1}}。
答案 1 :(得分:2)
变量p是指向int(指向a)的指针
表达式* p取消引用指针,因此就像直接访问int一样。
指针p上的operator postfix ++优先于解除引用。因此* p ++递增指针p(对于int之后的内存中的任何垃圾)在计算表达式之后,解除引用仍然解析为a,这就是打印10的原因。但是在运行语句之后,p的值会改变。因此,如果你使用printf(“%u”,* p),可能在该语句之后你会得到一个尴尬的价值。
但是,如果执行++ * p,则表达式将在p指向的dereferenced int变量上计算为++运算。如果你想避免这样的麻烦,当不确定时,使用括号:
(*p)++
++(*p)
而且你确定你正在取消引用价值并采取行动。增加指针值是C和C ++等语言允许的非常危险的操作,所以尽量避免!
答案 2 :(得分:2)
表达式*p++
中的后增量运算符适用于指针,而不是存储在该位置的值,因此在评估之后或之前的结果永远不会是11。表达式*p++
表示:取消引用p
(获取它的值)然后将p
增加一个位置。由于p
指向int
,因此递增它会将其向前移动sizeof(int)
个字节。添加永远不适用于p
指向的值,即10。
然而,表达式(* p)++是不同的。它取消引用p(获取其值),然后递增该内存位置中的值。表达式求值为原始值。所以在执行语句
之后int c = (*p)++;
变量c
等于10,而a
等于11。
答案 3 :(得分: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
}。
答案 4 :(得分:2)
[C11:§6.5.2.4/ 2]:postfix ++运算符的结果是操作数的值。作为副作用,操作数对象的值会递增(即,将相应类型的值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
的类型为 pointer-to-int 。因此,1
缩放为sizeof (int)
。
因此,p现在指向int
地址:p + sizeof (int)
答案 5 :(得分:1)
我只想加五美分
要通过指针增加值间接值,您可以使用++*ip
或(*ip)++
。关于K&amp; R书中括号的一个很好的解释:
在最后一个例子中,括号是必要的
(*ip)++
;没有他们,他们表达 将增加ip而不是它指向的内容,因为 像*和++这样的一元运算符从右到左关联。
在您的代码中,您得到10,因为printf将打印变量的原始值,并且只有在使用postfix ++
运算符后才会增加1。