增加指针,精确序列

pyr*_*hic 8 c pointers increment

我刚刚开始学习C,我明白了

*a = *b;
a++;
b++;
Run Code Online (Sandbox Code Playgroud)

*a++ = *b++
Run Code Online (Sandbox Code Playgroud)

是等价的,但这就是线路时实际发生的事情

*a++ = *b++
Run Code Online (Sandbox Code Playgroud)

叫做?有人可以澄清编译器如何解释第二行吗?我知道从右到左的优先级等等,但是有人可以准确地编写编译器用来解释这行代码的步骤吗?

Eri*_*ert 13

你说你相信:

*a = *b; a++; b++;
Run Code Online (Sandbox Code Playgroud)

相当于

*a++ = *b++;
Run Code Online (Sandbox Code Playgroud)

但这是错误的,所以你有一个错误的信念.让我们纠正你的错误信念.

在第一种情况下,必须发生以下事情:

  • VAR:*a必须进行评估才能生成变量,调用它var
  • VAL:*b必须进行评估以产生一个值,然后调用它val
  • ASSIGN:val必须分配给var.
  • INCA:a必须递增.
  • INCB:b必须递增.

编译器如何订购这些限制有哪些限制?

  • VAR和VAL必须在ASSIGN之前发生.
  • ASSIGN必须在INCA之前发生.
  • INCA必须在INCB之前发生.

这里的规则是在下一个语句开始之前必须完成一个语句的所有副作用.所以有两种法律秩序.VAR VAL ASSIGN INCA INCB,或VAL VAR ASSIGN INCA INCB.

现在让我们考虑第二种情况.

*a++ = *b++;
Run Code Online (Sandbox Code Playgroud)

我们有相同的五个操作,但它们的排序约束完全不同,因为它们都在同一个语句中,所以关于语句的规则不适用.现在的限制是:

  • VAR和VAL必须在ASSIGN之前发生.
  • VAR的评估必须使用原始值 a
  • VAL的评估必须使用原始值 b

请注意,我没有说增量必须在之后发生.相反,我说必须使用原始值. 只要使用原始值,增量就可以随时发生.

因此,例如,将其生成为完全合法

var = a;
a = a + 1; // increment a before assign
*var = *b;
b = b + 1; // increment b after assign
Run Code Online (Sandbox Code Playgroud)

这样做也是合法的:

val = *b;
b = b + 1; // increment b before assign
*a = val;
a = a + 1; // increment a after assign
Run Code Online (Sandbox Code Playgroud)

按照您的建议进行操作也是合法的:首先进行分配,然后按从左到右的顺序进行增量.首先进行分配也是合法的,然后以从右到左的顺序进行增量.

AC编译器具有广泛的自由度来生成代码,但它喜欢这种表达式.确保这一点在你的脑海中非常清楚,因为大多数人都错了:只是因为++变量之后并不意味着增量发生得晚.只要编译器确保使用原始值,增量就可以在编译器喜欢的时候发生.

这是C和C++的规则.在C#中,语言规范要求赋值左侧的副作用发生赋值右侧的副作用之前,并且两者都发生在赋值的副作用之前.C#中的相同代码将需要生成为:

var_a = a;
a = a + 1;
// must pointer check var_a here
var_b = b;
b = b + 1;
val = *var_b; // pointer checks var_b
*var_a = val;
Run Code Online (Sandbox Code Playgroud)

"指针检查"是C#要求运行时验证var_a是有效指针的点; 换句话说,那*var_a实际上是一个变量.如果不是那么它必须 b评估之前抛出异常.

同样,允许 C编译器以C#方式执行,但不是必需的.

  • 所以表达式'a =*p ++;`以2种方式执行**(1)**首先在某些VAR中分配,然后因为`++`具有更高的优先级所以`p`更新为指向下一个位置,然后在*第二步*旧的值'p` = VAR分配给`a`为`a =*VAR`.**(2)**首先`*p`赋值给`a`,因为`++`是后缀运算符然后'p`更新指向下一个位置. (2认同)
  • @GrijeshChauhan:正确; 在C中订购是合法的.在C#中,规范要求首先产生左侧的副作用(如果有的话).然后发生"p"增量的副作用,然后解除引用旧的"p"值的副作用(记住,如果指针无效,则解除引用会在C#中产生副作用),然后是副作用分配发生了.也就是说,在C#中,对于子表达式,副作用从左到右*发生,对于运算符,*以优先顺序*发生. (2认同)