首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言問答

C語言 do-while 循環陷阱:複合條件 --x 與 ! 運算符深度解析

     編輯:C 語言問答

經典面試題:輸出 1, -2 後為何停止?

題目代碼

#include <stdio.h>

int main() {
    int x = 3;
    do {
        printf("%d\n", x -= 2);
    } while (!(--x));
    return 0;
}
// 輸出: 1, -2

逐步執行追蹤表

輪次x 初值x -= 2printf 輸出--x (前置遞減)! (邏輯非)while 判斷動作
131101 (真)true繼續循環
20-2-2-30 (假)false退出循環

關鍵運算符優先級與結合性

while (!(--x))
// 解析順序(由高到低):
// 1. --x  (前置遞減,右結合)
// 2. !    (邏輯非,右結合)
// 3. while 判斷整個表達式值

// 等價展開:
temp = --x;   // x = x - 1,取新值
cond = !temp; // 邏輯非:0→1,非0→0
if (cond) continue; else break;

核心邏輯解析

  1. do-while 至少執行一次:無條件進入循環體
  2. x -= 2 先執行:x = 3 → 1,輸出 1
  3. --x 後執行:x = 1 → 0
  4. !0 = 1 (真):條件為真,繼續循環
  5. 第二輪:x = 0 → -2 (輸出),x = -2 → -3
  6. !(-3) = 0 (假):條件為假,退出循環

邏輯非 ! 運算符真值表

運算元結果說明
01假變真
非 0 (含負數)0真變假

變體練習

// 變體 1:去掉邏輯非
do { printf("%d\n", x -= 2); } while (--x);
// x: 3→1(輸出1)→0(假)停止。輸出: 1

// 變體 2:後置遞減
do { printf("%d\n", x -= 2); } while (!(x--));
// x: 3→1(輸出1)→1(真)→ -1(輸出-1)→-2(真)→-3(輸出-3)→-4(真)...無限循環!

// 變體 3:分離條件判斷(更清晰)
do {
    x -= 2;
    printf("%d\n", x);
    x--;  // 等價於 --x 在條件中
} while (x != 0);  // 明確語義:x 不為 0 繼續

最佳實踐建議

  • 避免在循環條件中做複雜副作用操作:將狀態變更移到循環體內,條件只做純判斷
  • 優先用 while/for 替代 do-while:除非確確實實需要「至少執行一次」
  • 複雜條件拆解為中間變量:可讀性 >> 炫技
  • 單元測試覆蓋邊界:x 初值為 0、1、2、3、負數等情況

等價重構版(推薦寫法)

int x = 3;
while (1) {           // 明確無限循環
    x -= 2;
    printf("%d\n", x);
    x--;              // 明確狀態變更
    if (x == 0) break; // 明確退出條件
}
// 輸出相同:1, -2
// 但邏輯清晰、易維護、易測試
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved