鱼C论坛

 找回密码
 立即注册
查看: 87|回复: 5

我又来啦,嘿嘿

[复制链接]
发表于 前天 00:25 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#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??帮忙解答一下~~整个程序又是如何?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 前天 00:26 | 显示全部楼层
你好!很高兴你又来提问了。这个程序涉及到了 C 语言中一个非常经典且容易混淆的问题:**函数参数求值顺序** 和 **副作用序列点**。

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

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

为什么会这样?

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

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

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

初始值: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。

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

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

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

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


  1. #include

  2. int main() // 使用标准的 int main()
  3. {
  4.     int i = 8;
  5.    
  6.     // 分开计算,顺序清晰明确
  7.     int a = ++i; // i=9, a=9
  8.     int b = --i; // i=8, b=8
  9.     int c = i++; // c=8, 然后i=9
  10.     int d = i--; // d=9, 然后i=8
  11.     int e = -i++; // e=-8, 然后i=9
  12.     int f = -i--; // f=-9, 然后i=8

  13.     printf("%d\n%d\n%d\n%d\n%d\n%d\n", a, b, c, d, e, f);
  14.     return 0;
  15. }
复制代码


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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 前天 00:41 | 显示全部楼层
未定义行为

#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??
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 前天 00:42 | 显示全部楼层
但求过程001 发表于 2025-09-02 00:41
未定义行为

#include

void  ...


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

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

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

初始状态: `i = 8`


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

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


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

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


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

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


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

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


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

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

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


  1. 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 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 前天 01:01 | 显示全部楼层
我知道我错哪了,我把“-”代入一起计算了,应该只是对变量i自加或自减,不能带“-”。
OK,感谢,今天又学到了一点点,晚安~~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 前天 01:02 | 显示全部楼层
但求过程001 发表于 2025-09-02 01:01
我知道我错哪了,我把“-”代入一起计算了,应该只是 ...


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

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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-9-4 20:36

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表