const char *cp = "steven";
while (*cp) {
putchar(*cp); /* 或 printf("%c", *cp); */
++cp;
}
| 步驟 | 表達式 | 副作用 / 結果 |
|---|---|---|
| 1 | cp | 指向字串常量區首字元 's' 的位址(唯讀) |
| 2 | *cp | 解引用取得字元值 's' (ASCII 115),非零 → 真 |
| 3 | putchar(*cp) | 輸出 's' |
| 4 | ++cp | 指針前移 sizeof(char) = 1 位元組,指向 't' |
| 5 | 循環判斷 | 重複 2-4,直到 *cp == '\0' (0) → 假,退出 |
lodsb / mov al, [rsi]; inc rsi 單指令循環\0 同時是「字串結束標記」與「布林假值」,完美契合 while (*p) 語義cp 同時扮演「當前元素位址」與「下一輪起始位址」++cp語意清晰「移動到下一字元」,無臨時值開銷。
cp++ 在循環條件中while (*cp++) putchar(cp[-1]); // 可行但晦澀:先取值後遞增,體內需用 cp[-1]
char *p = "hello"; // 警告:棄棄 const
*p = 'H'; // UB:段錯誤(寫入唯讀段)
正確:char arr[] = "hello"; arr[0] = 'H'; 或 char *p = strdup("hello");
const char *cp = get_string(); // 可能返回 NULL
while (*cp) { ... } // UB:解引用 NULL
防禦:if (!cp) return; while (*cp) ...
/* 計算長度(手寫 strlen) */
size_t my_strlen(const char *s) {
const char *p = s;
while (*p) ++p;
return p - s;
}
/* 複製(手寫 strcpy) */
char *my_strcpy(char *dst, const char *src) {
char *d = dst;
while ((*d++ = *src++)) ; /* 賦值結果即字元值,\0 為 0 結束 */
return dst;
}
/* 大小寫轉換 */
void str_toupper(char *s) {
for (char *p = s; *p; ++p)
*p = (char)toupper((unsigned char)*p);
}
| 方法 | 優點 | 缺點 |
|---|---|---|
指針算術 while(*p) | 極快、零依賴、嵌入式首選 | 手動管理、易越界、需懂 UB |
索引 for(i=0;s[i];++i) | 直觀、易除錯 | 隱含乘法(編譯器通常優化掉) |
for (char c : str) (C++) | 範圍-based、安全 | 需 C++、隱式複製/引用 |
string_view (C++17) | 零拷貝視圖、豐富 API | 僅 C++ |
while (*cp) { ...; ++cp; } 是 C 語言處理字串的原子操作模式。它展示了指針算術、空終止約定、零開銷循環三大 C 核心哲學的完美融合。掌握並內化此模式,是通往「系統級 C 程式設計師」的必經之路。