指针,后增量运算符和序列点

bab*_*bon 1 c pointers

当我运行这个玩具程序时,

#include<stdio.h>

int main(void)
{
    int arr[] = {11, 22, 33};
    int *ptr = arr;
    printf("ptr at: %p\n", (void *)ptr);
    printf("Result of expression: %d\n", *ptr++);  // line 8
    printf("ptr at: %p\n", (void *)ptr);
}
Run Code Online (Sandbox Code Playgroud)

我得到的输出是:

ptr at: 0x7fffffffdbf0
Result of expression: 11
ptr at: 0x7fffffffdbf4
Run Code Online (Sandbox Code Playgroud)

我对发生的事情的理解line 8是,根据优先规则(后增量的++优先级高于取消引用*),表达式*ptr++相当于*(ptr++).这是我经历的一个很好的解释.但是,在那个解释中没有提到序列点.

在混合中抛出序列点,我假设它11是打印的,因为ptr只有在达到序列点(恰好在所有要printf计算的参数之后)才会增加.并且,后增量运算符实际上是在序列点之后完成它(增加和写入)的工作.我的理解是否正确?

Jer*_*myP 6

我假设打印11是因为ptr仅在序列点之后递增(恰好在printf的所有参数被评估之后)

不.这与序列点无关.后增量表达式增加其参数,但表达式的值是增量前的参数值.

对于int*post增量看起来很像这个函数:

int* postInc(int** p)
{
    int* tmp = *p;
    *p = *p + 1;
    return tmp;
}
Run Code Online (Sandbox Code Playgroud)

而且*p++应该是这样的:

*postInc(&p);
Run Code Online (Sandbox Code Playgroud)


Lun*_*din 5

我对第8行发生的事情的理解是,根据优先规则(后增量++的优先级高于去引用*)表达式*ptr ++相当于*(ptr ++)

这是对的.

在混合中投掷序列点......

这与序列点本身没有任何关系,而是与postfix ++的行为有关,指定为(6.5.2.4):

postfix ++运算符的结果是操作数的值.作为副作用,操作数对象的值递增.
/ - /
在更新操作数的存储值的副作用之前,对结果的值计算进行排序.

在简单的英语中,这意味着表达式ptr++将首先"返回" ptr将用作表达式结果的值,然后再增加ptr1.

对于整个表达式printf("Result of expression: %d\n", *ptr++);,在评估所有函数参数之后,但在调用函数之前有一个序列点.再加上一些.

程序流程如下:

  1. 评估两个表达式"Result of expression: %d\n"和*ptr++.这可以按任何顺序完成.
  2. 对于子表达式*ptr++,请评估其子表达式.运算符优先级指示生成ptr++一个子表达式.因此,将此表达式计算为值ptr并存储结果.

  3. a)*使用存储的结果作为操作数评估运算符.存储评估结果,以传递给函数.
    b)增加ptr1.
    3a)和3b)可以相对于彼此以任何顺序排序.

  4. 评估传递给printf的所有函数参数.
  5. 序列点.
  6. 执行printf.
  7. 在printf返回之前的序列点.
  8. 序列点在;.

如您所见,序列点与*ptr++表达式的评估大多无关.序列点发挥作用的唯一时间是C指示++必须在它之前发生.但++可以发生在2)和5)之间的任何地方.