while (n-- > 0) 的用法

本文介绍了在Java中使用while循环的一种新颖方式:while(n-->0),这种方式可以用来替代常见的for循环,实现循环n次的功能。此外还对比了while(--n>=0)等其他循环写法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     今天写java算法的时候碰到了while (n-- > 0) 这个东东,瞬间迷惑了,然后找度娘了解了一下

它的意思是循环n次,除了最常用的 for (int i = 0; i < n; ++i) {...} 之外,还可以写 while (n-- > 0) {...}while (--n >= 0) {...}

  写个随手笔记,不喜勿喷!!!


<think>我们正在讨论两个表达式:`n-- > 0` 和 `n- -> 0`(注意第二个表达式中间有空格,即`n-- > 0`与`n- ->0`的区别)。在C/C++中,运算符的结合性和优先级决定了表达式的解析方式。 ### 一、表达式 `n-- > 0` 的解析 1. **词法分析**: - `n--`:后缀自减运算符(优先级2级,结合性从左到右)[^3]。 - `>`:关系运算符(优先级6级,结合性从左到右)[^3]。 2. **解析结果**: 表达式被解析为 `(n--) > 0`。 - 先计算 `n--`:返回`n`的当前值,然后将`n`减1(副作用稍后发生)。 - 然后比较返回值是否大于0。 3. **示例**: 若初始 `n=1`: - `n--` 返回1,然后`n`变为0- `1 > 0` 结果为 `true`。 --- ### 二、表达式 `n- -> 0` 的解析(注意空格) 1. **词法分析**: - `n-`:被解析为二元减法运算符(优先级6级)的一部分,但这里实际是`->`运算符的前半部分。 - `->`:箭头运算符(优先级2级,结合性从左到右)[^2][^4]。 2. **关键点**: - 当编译器遇到 `n-` 后紧接 `->` 时,会将其识别为**连续的运算符序列**,但实际语法要求`->`必须是一个整体(不能拆分)。 - 因此,表达式 `n- -> 0` 会被解析为 `(n) - (->0)`,而 `->0` 本身是非法语法。 3. **错误原因**: - `->` 是**结构体指针成员访问运算符**,要求左操作数是指针类型[^2][^4]。 - 若`n`是结构体指针,正确写法应为 `n->0`,但`0`必须是成员名(不能是数字)。 - 若`n`不是指针,则 `n->0` 直接非法。 --- ### 三、对比总结 | 表达式 | 实际解析 | 是否合法 | 含义 | |-------------|----------------|----------|--------------------------| | `n-- > 0` | `(n--) > 0` | 合法 ✅ | 比较`n`自减前的值是否>0 | | `n- -> 0` | 语法错误 ❌ | 非法 | 箭头运算符使用错误 | > **关键区别**: > - `n-- > 0` 是合法的关系表达式。 > - `n- -> 0` 因空格拆分导致解析失败(或意图访问结构体成员但语法错误)。 --- ### 四、结合性与优先级的作用 1. **运算符优先级**: 后缀 `++`/`--`(优先级2级)高于关系运算符 `>`(优先级6级),因此 `n-- > 0` 被正确分组为 `(n--) > 0`[^3]。 2. **结合性**: 关系运算符从左到右结合,但此处仅有一个运算符,无影响。 --- ### 五、常见误区 - **空格的影响**: 在C/C++中,空格通常不影响语义,但可能改变词法分析结果: - `a---b` 被解析为 `(a--) - b`(最长匹配)。 - `a -- - b` 与 `a---b` 等价。 - 但 `a- --b` 会被解析为 `a - (--b)`。 - **箭头运算符的完整性**: `->` 是一个不可分割的运算符,空格不能插入中间(如 `n - > 0` 会解析为 `n - (>0)`,而 `>0` 是非法表达式)。 --- ### 六、正确使用建议 1. **避免混淆写法**: ```c // 明确意图的写法 if (n-- > 0) { ... } // 合法:比较后自减 // 若需访问结构体成员 struct S *p = ...; if (p->value > 0) { ... } // 合法:比较成员值 ``` 2. **理解运算符完整性**: - 后缀/前缀运算符(`++`/`--`)必须紧贴变量。 - 箭头运算符(`->`)必须连续书写。 > **最终结论**:`n-- > 0` 是常见循环条件(如 `while(n-- > 0)`),而 `n- -> 0` 是语法错误,因箭头运算符使用不当。 §§相关问题§§ 1. C/C++中后缀自增(`a++`)和前缀自增(`++a`)在性能上有差异吗? 2. 如何理解C语言中的“序列点(sequence point)”对自增/自减副作用的影响? 3. C/C++中哪些运算符的组合容易导致解析歧义? 4. 结构体指针访问成员时,`.` 和 `->` 的使用场景有何区别?</think>### C/C++运算符结合性与表达式解析详解 #### 一、`n-- > 0` 的解析(合法表达式) 1. **词法分析**: - `n--`:后缀自减运算符(优先级2级) - `>`:关系运算符(优先级6级) - 解析为:`(n--) > 0` 2. **执行顺序**: ```c int n = 5; while (n-- > 0) { // 循环体 } ``` - 先返回`n`的当前值 - 再执行`n = n - 1` - 最后比较返回值与0 - *等价于*:`(n > 0)` 判断后执行 `n = n - 1` 3. **结合性影响**: - 后缀`--`优先级(2级) > 关系运算符`>`(6级) - 从左向右结合:先处理`n--`再处理`>` #### 二、`n- -> 0` 的解析(非法表达式) 1. **词法分析**: - 编译器尝试最长匹配:识别为`->`运算符 - 但`->`要求左操作数是**指针类型** - 解析为:`n->0`(结构体指针访问成员) 2. **错误原因**: ```c struct Data { int x; }; struct Data *ptr = &data; // 合法用法 ptr->x = 10; // ✅ 访问成员x // 非法用法 n- -> 0; // ❌ 错误1:n不是指针 // ❌ 错误2:0不是有效成员名 ``` - 编译器报错:`left operand of '->' must be pointer` #### 三、关键对比表 | 特性 | `n-- > 0` | `n- -> 0` | |---------------------|-------------------------------|--------------------------------| | **合法性** | 合法 ✅ | 非法 ❌ | | **运算符类型** | 后缀自减+关系运算符 | 结构体成员访问运算符 | | **操作数要求** | 数值类型 | 左操作数必须是指针 | | **实际含义** | 判断n自减前的值是否大于0 | 试图访问结构体成员"0" | | **等效解析** | `(tmp=n, n-=1, tmp>0)` | 语法错误 | #### 四、结合性规则详解 1. **优先级层级**(从高到低): ```plaintext 1. 后缀 ++ -- [] () . 2. 前缀 ++ -- + - ! ~ (type)* & sizeof 3. * / % // 乘除 4. + - // 加减 5. < <= > >= // 关系运算符 6. == != // 相等判断 ... [^3] ``` 2. **结合性案例**: ```c a * b / c // 等价于 (a * b) / c(左结合) !~n // 等价于 !(~n)(右结合) ``` #### 五、正确使用建议 1. **避免歧义写法**: ```c // 推荐明确写法 (n--) > 0 // ✅ 明确意图 ``` 2. **结构体访问规范**: ```c struct Point { int x; y; }; struct Point p1 = {1,2}; struct Point *ptr = &p1; p1.x = 10; // . 用于结构体变量 ptr->y = 20; // -> 用于结构体指针[^2][^4] ``` > **关键结论**:`n-- > 0` 是合法的自减比较,而 `n- -> 0` 是语法错误,源于箭头运算符的误用和结合性规则的冲突。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值