C switch 语句中的指针操作
C Pointer manipulation in switch statement
大家好,我尝试编写一个简单的 switch 语句,但遇到了这个问题。
我不明白为什么这段代码能正常工作,我猜是因为运算符 ** 和 ++ 的优先级。
如果是这种情况,如果有人可以写一个示例我应该如何在如下语句中使用 value-at * 和 inc/dec 运算符,我会很高兴。
提前致谢,
while (--argc > 0)
argv++;
switch (**argv)
而这段代码没有
while (--argc > 0)
switch (**(argv++))
完整代码:
while (--argc > 0) {
switch (**(argv++)) {
case '[=12=]':
panic("empty command line argument");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
push (atof(*argv));
break;
case '+':
push(pop() + pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '*':
push(pop() * pop());
break;
case '/':
op2 = pop();
push(pop() / op2);
break;
default:
panic("unknown command");
break;
}
}
在任何表达式中对给定变量使用后增量会导致变量在计算表达式后递增。
正如您的第一个工作代码所述,在argv
值之前在开关中获取它的引用值,您希望变量增加before 你的表达式被评估,所以你需要使用预增量:
while (--argc > 0)
switch (**(++argv))
我认为您被括号弄糊涂了。括号会影响评估的顺序,但您使用的是 post 增量,无论运算符的评估顺序如何,它都会在最后应用。
在您的第一个片段中,顺序很明确:首先增加 argv,然后取消引用它。也就是说,您取消引用 "next" 元素,而不是当前元素。
在您的第二个代码段中,您想要获得相同的结果,并且您正在使用括号。这不是解决方案。括号会影响 2 个运算符(++
和 **
) 求值 的顺序,但这并不意味着效果会按该顺序应用。
例如:如果你写了
switch ((**argv)++)
编译器会首先应用 **
,取消引用它,给你内容,然后它会在上面应用 ++
(显然 argv
必须是一种数据类型,它可以增加或会出现错误,但这里无关紧要)。相反,如果你像你那样写,
switch (**(argv++))
首先应用增量 (++
),然后应用间接 (**
)。但这里有诀窍:post增量仍然是post增量。在这里应用 post 增量意味着:取 current 值,当一切完成后记得增加它。所以 argv
按原样使用,没有增加它(还),并发送到 **
,这将给出 current 值(不是下一个! ).然后,在 switch
读取当前元素后,argv 增加(post-增量),因此如果您的 case
打印 **argv
,您会注意到它是 "next"值。
一个解决方案正在使用预增量:
switch (**(++argv))
但如果您问我,真正的解决方案是完全避免这些令人头疼的问题,将代码分两行编写,这样一来发生的事情就一目了然。正如您在第一个片段中所做的那样。这是最易读的风格,因此应该是首选。然后你就可以忘记一切:计算顺序、括号、pre- vs post-increment、结合性。
大家好,我尝试编写一个简单的 switch 语句,但遇到了这个问题。 我不明白为什么这段代码能正常工作,我猜是因为运算符 ** 和 ++ 的优先级。 如果是这种情况,如果有人可以写一个示例我应该如何在如下语句中使用 value-at * 和 inc/dec 运算符,我会很高兴。
提前致谢,
while (--argc > 0)
argv++;
switch (**argv)
而这段代码没有
while (--argc > 0)
switch (**(argv++))
完整代码:
while (--argc > 0) {
switch (**(argv++)) {
case '[=12=]':
panic("empty command line argument");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
push (atof(*argv));
break;
case '+':
push(pop() + pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '*':
push(pop() * pop());
break;
case '/':
op2 = pop();
push(pop() / op2);
break;
default:
panic("unknown command");
break;
}
}
在任何表达式中对给定变量使用后增量会导致变量在计算表达式后递增。
正如您的第一个工作代码所述,在argv
值之前在开关中获取它的引用值,您希望变量增加before 你的表达式被评估,所以你需要使用预增量:
while (--argc > 0)
switch (**(++argv))
我认为您被括号弄糊涂了。括号会影响评估的顺序,但您使用的是 post 增量,无论运算符的评估顺序如何,它都会在最后应用。
在您的第一个片段中,顺序很明确:首先增加 argv,然后取消引用它。也就是说,您取消引用 "next" 元素,而不是当前元素。
在您的第二个代码段中,您想要获得相同的结果,并且您正在使用括号。这不是解决方案。括号会影响 2 个运算符(++
和 **
) 求值 的顺序,但这并不意味着效果会按该顺序应用。
例如:如果你写了
switch ((**argv)++)
编译器会首先应用 **
,取消引用它,给你内容,然后它会在上面应用 ++
(显然 argv
必须是一种数据类型,它可以增加或会出现错误,但这里无关紧要)。相反,如果你像你那样写,
switch (**(argv++))
首先应用增量 (++
),然后应用间接 (**
)。但这里有诀窍:post增量仍然是post增量。在这里应用 post 增量意味着:取 current 值,当一切完成后记得增加它。所以 argv
按原样使用,没有增加它(还),并发送到 **
,这将给出 current 值(不是下一个! ).然后,在 switch
读取当前元素后,argv 增加(post-增量),因此如果您的 case
打印 **argv
,您会注意到它是 "next"值。
一个解决方案正在使用预增量:
switch (**(++argv))
但如果您问我,真正的解决方案是完全避免这些令人头疼的问题,将代码分两行编写,这样一来发生的事情就一目了然。正如您在第一个片段中所做的那样。这是最易读的风格,因此应该是首选。然后你就可以忘记一切:计算顺序、括号、pre- vs post-increment、结合性。