但求过程001 发表于 4 天前

我又来啦,嘿嘿

#include <stdio.h>

void main()

{
        int i=8;
        printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i++,i--,-i++,-i--);
}


如上程序,这个第一个输出运行结果为8,我就不懂了。。。++i怎么会是8??帮忙解答一下~~整个程序又是如何?

FishC 发表于 4 天前

你好!很高兴你又来提问了。这个程序涉及到了 C 语言中一个非常经典且容易混淆的问题:**函数参数求值顺序** 和 **副作用序列点**。

简单来说,这个程序的输出结果是 未定义行为(Undefined Behavior)。也就是说,不同的编译器、不同的编译设置甚至不同的运行环境,都可能产生不同的结果。

你看到第一个输出是 8,而你认为 ++i 应该是 9。这完全合理,但编译器可能不是按照你想象的从左到右的顺序来计算这些参数的。

为什么会这样?

1.关键问题:参数求值顺序
    C 语言标准并没有规定函数参数的计算顺序。编译器可以自由选择先计算哪个参数。它可能从右向左算,也可能从左向右算,甚至用其他更复杂的方式。

2.致命问题:修改同一变量多次
    在同一个表达式里,你对同一个变量 i 进行了多次修改(++i, --i, i++, i--),并且这些修改之间没有 序列点 (Sequence Point) 来保证执行顺序。这直接导致了未定义行为。

一个可能的计算过程(以从右向左为例)
许多编译器选择从右向左计算参数并压入栈中。我们来看看如果按照这个顺序,会发生什么:

初始值:i = 8

1.计算最右边的 -i--:
    *   i-- 是后减,所以先取 i 的值 8 参与运算,然后 i 再减 1 变成 7。
    *   -8 等于 -8。
    *   此时,第一个被计算出的参数值是 -8,并且 i 变成了 7。

2.计算 -i++:
    *   i++ 是后加,先取 i 的当前值 7 参与运算,然后 i 再加 1 变成 8。
    *   -7 等于 -7。
    *   此时,i 又变回了 8。

3.计算 i--:
    *   后减,先取 i 的当前值 8 参与运算,然后 i 再减 1 变成 7。
    *   参数值是 8。

4.计算 i++:
    *   后加,先取 i 的当前值 7 参与运算,然后 i 再加 1 变成 8。
    *   参数值是 7。

5.计算 --i:
    *   前减,i 先减 1 变成 7,然后使用新值 7 参与运算。
    *   参数值是 7。

6.计算最左边的 ++i:
    *   前加,i 先加 1 变成 8,然后使用新值 8 参与运算。
    *   参数值是 8。

现在,参数栈从右向左(计算顺序)是: [-8, -7, 8, 7, 7, 8]
而 printf 打印时是从左向右(格式符顺序)取用这些值,所以输出就成了:
8
7
7
8
-7
-8

这就是你看到的第一个输出是 8 的原因。在这个计算过程中,最后的 ++i 计算完后,i 的值正好是 8。

最重要的结论
你不需要记住这个过程,也千万不要在真正的代码里这样写!记住这个核心原则:

绝对不要在同一条语句中,对同一个变量进行多次自增(++)或自减(--)操作。

这是一种糟糕的编程风格,会导致代码不可移植且难以理解。

正确的做法
把计算和打印分开,让逻辑变得清晰:


#include

int main() // 使用标准的 int main()
{
    int i = 8;
   
    // 分开计算,顺序清晰明确
    int a = ++i; // i=9, a=9
    int b = --i; // i=8, b=8
    int c = i++; // c=8, 然后i=9
    int d = i--; // d=9, 然后i=8
    int e = -i++; // e=-8, 然后i=9
    int f = -i--; // f=-9, 然后i=8

    printf("%d\n%d\n%d\n%d\n%d\n%d\n", a, b, c, d, e, f);
    return 0;
}


希望这个解释能帮你解开疑惑!编程中清晰和稳定远比炫技更重要。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

但求过程001 发表于 4 天前

未定义行为{:5_106:}{:5_106:}

#include <stdio.h>

void main()

{
        int i=8;
        printf("%d\n",++i);
        printf("%d\n",--i);
        printf("%d\n",i++);
        printf("%d\n",i--);
        printf("%d\n",-i++);
        printf("%d\n",-i--);
}

是不是这个程序就更标准一些,但是运行结果前5个没有问题我计算的,最后一个输出值为-9,我怎么算的是7??

FishC 发表于 4 天前

但求过程001 发表于 2025-09-02 00:41
未定义行为{:5_106:}{:5_106:}

#include

void...

你观察得非常仔细,而且能提出这个问题,说明你已经掌握了各个运算符单独的作用!这非常棒。

我们来一步步拆解这个程序,你会发现你的计算在最后两步可能出了一个小偏差。

这个程序写得非常好,完全避免了“未定义行为”,因为每个 `printf` 语句都是一个完整的序列点,执行顺序非常明确。

初始状态: `i = 8`


printf("%d\n",++i); // 前加:i 先自增1变成9,然后打印9。

*   **执行后:i = 9, 输出:9**


printf("%d\n",--i); // 前减:i 先自减1变成8,然后打印8。

*   **执行后:i = 8, 输出:8**


printf("%d\n",i++); // 后加:先打印i的当前值8,然后i自增1变成9。

*   **执行后:i = 9, 输出:8**


printf("%d\n",i--); // 后减:先打印i的当前值9,然后i自减1变成8。

*   **执行后:i = 8, 输出:9**


printf("%d\n",-i++); // 后加:先取i的值8进行负号操作得-8并打印,然后i自增1变成9。

*   **执行后:i = 9, 输出:-8**

关键的一步来了!现在 `i` 的值是 9。


printf("%d\n",-i--); // 后减:先取i的当前值9进行负号操作得-9并打印,然后i自减1变成8。

*   **执行后:i = 8, 输出:-9**

所以,整个程序的输出顺序是:
9
8
8
9
-8
-9

你觉得最后应该是7,我猜你的计算过程可能是这样的:
在经历了 `-i++` 之后,你可能认为 i 又进行了一次自减,变成了 7,然后对 7 取负。

但实际上,在 `-i--` 这一步,运算符是 `--`,它的优先级高于负号 `-`,但因为它是一个“后减”操作,所以规则是:**先使用 i 的值参与负号运算,运算完成后再进行自减**。

所以,参与运算的值是 i 的当前值 9,取负后得到 -9 并打印。在这条语句执行完后,i 才被减为 8。

总结一下:
这个程序非常标准,结果也是确定无疑的。你只是最后一步在“先使用后自减”这个点上和编译器的实际执行产生了一点分歧。

希望这个详细的分解能帮你彻底搞清楚!继续保持这种钻研精神!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

但求过程001 发表于 4 天前

我知道我错哪了,我把“-”代入一起计算了,应该只是对变量i自加或自减,不能带“-”。
OK,感谢,今天又学到了一点点,晚安~~

FishC 发表于 4 天前

但求过程001 发表于 2025-09-02 01:01
我知道我错哪了,我把“-”代入一起计算了,应该只是 ...

你总结得非常到位,完全正确!就是这个意思。

-i++ 和 -i-- 里的负号 - 只是一个独立的“取负”操作符,它并不会改变 ++ 或 -- 这两个运算符本身对变量 i 进行“自增”或“自减”的核心操作。

你能自己发现并总结出这个关键点,真的太棒了!这才是最有效的学习方式。

不客气,很高兴能帮到你。晚安,好梦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 我又来啦,嘿嘿