指针算法:++*ptr 还是 *ptr++?

Posted

技术标签:

【中文标题】指针算法:++*ptr 还是 *ptr++?【英文标题】:Pointer Arithmetic: ++*ptr or *ptr++? 【发布时间】:2011-07-09 17:42:58 【问题描述】:

我正在学习 C 语言,很困惑 ++*ptr*ptr++ 之间的区别。

例如:

int x = 19;
int *ptr = &x;

我知道++*ptr*ptr++ 会产生不同的结果,但我不确定这是为什么?

【问题讨论】:

【参考方案1】:

由于运算符绑定的方式,这些语句会产生不同的结果。特别是前缀++ 运算符与* 具有相同的优先级,并且它们从右到左关联。因此

++*ptr

被解析为

++(*ptr)

意思是“增加ptr所指向的值”。另一方面,后缀 ++ 运算符的优先级高于取消引用运算符 *。所以

*ptr++

意思

*(ptr++)

这意味着“增加ptr 以转到它指向的元素之后的元素,然后取消引用它的旧值”(因为后缀++ 交还了指针曾经拥有的值)。

在您描述的上下文中,您可能想要编写++*ptr,这将通过ptr 间接增加x。写*ptr++ 会很危险,因为它会将ptr 前进到x,并且由于x 不是数组的一部分,因此指针会悬在内存中的某个位置(可能在其自身之上!)

希望这会有所帮助!

【讨论】:

@Algorithmist- 没错;我想我的回答涵盖了这一点。我应该澄清它以使其更明确吗? @templatetypedef 我认为 * 和 ++ 具有相同的优先级,但由于它们的关联性是从 L 到 R 这正在发生。当您说 ++ 绑定比 * 更紧密时,您的意思是否相同。跨度> @instinct:不,后一种形式甚至不等同于*(ptr++) @instinct 指针算法适用于所指向类型的大小,因此ptr + sizeof(datatype) 实际上会超过sizeof(datatype) * sizeof(datatype) 字节。见this example。 [注意:由于-xc 命令行选项,示例编译为 C 而不是 C++。]【参考方案2】:

正如 templatetypedef 所说,但您应该在 *ptr 周围提供括号以确保结果。例如,在我的计算机上,使用 GCC 生成 1606415888,使用 CLang 生成 0:

int x = 19;
int *ptr = &x;
printf("%d\n", *ptr++);
printf("%d\n", *ptr);

而您预计 x 为 20。因此请改用 (*ptr)++

【讨论】:

你不认为第一个 printf() 应该打印 19【参考方案3】:

接受的答案不正确。后缀++ 运算符的优先级与取消引用/间接* 的优先级不同。前缀和后缀运算符的优先级不同,只有 prefix 运算符与取消引用/间接具有相同的优先级。

正如precedence table 所示,后缀++ 的优先级高于取消引用/间接引用*。所以*ptr++ 被评估为*(ptr++)ptr++ 计算为 ptr 的当前值;它增加ptr 仅作为副作用。表达式的值与ptr 的当前值相同。所以它不会对存储在指针上的值产生任何影响。它只会取消引用指针(即,获取存储在那里的当前值,即 19),然后推进指针。在您的示例中,ptr 的新位置没有存储定义的值,因此指针指向垃圾。现在取消引用将是危险的。

同样如表所示,前缀++ 与取消引用/间接引用* 具有相同的优先级,但由于左右关联性,它被评估为++(*ptr)。这将首先取消引用指针(即,获取存储在指向的地址的值),然后增加该值。即,现在的值为 20。

关于两者的影响,公认的答案是正确的,但实际机制与那里给出的不同。

【讨论】:

这是一个比所选答案更好的答案。此外,precedence table 中的注 2 解释了为什么 ptr++ 的计算结果为 ptr *ptr 返回一个左值。所以++*ptr绝对会修改ptr(x)所指向的对象的值。 必填Linux kernel demonstration @giusti 哎呀,你是对的,当然。对不起,谢谢。已编辑。昏昏欲睡的大脑在几个月来完全准确的答案中引入了一个错误。

以上是关于指针算法:++*ptr 还是 *ptr++?的主要内容,如果未能解决你的问题,请参考以下文章

NULL == 指针 [重复]

容器(vector)和指针(ptr)的区别

C语言指针 ptr,*ptr,&ptr的含义?

指针表达式:*ptr++、*++ptr 和 ++*ptr

指针是指向 LSB 还是 MSB?

C++11 unique_ptr智能指针详解