C语言递归回文检查中指针算术表达式取值异常问题
异常现象核心成因
你观察到的“指针、长度参数都按预期更新,但尾部字符始终返回固定值”,本质是递归传参的偏移增量完全抵消导致的:
- 每次递归你给
p_string加1、给length减1,两者的变化量大小相等、方向相反,使得p_string + length的整体值从第一次调用开始就恒定不变。- 取尾部字符的表达式
*(p_string + length -1)依赖的就是这个恒定的地址值,自然永远指向同一个内存位置,输出同一个固定字符,和你描述的现象完全吻合。这也解释了为什么你尝试把取地址表达式调整为*(p_string + length),依然会返回固定字符——因为这个表达式依赖的地址值从递归第一层开始就从未变化过。
递归逻辑的问题修正
现有逻辑的可取部分
逐次比对首尾字符、匹配则向内收缩比对范围的核心思路是成立的,这是回文递归判断的标准实现路径,没有方向上的错误。
需要调整的两处细节
- 收缩区间的长度计算错误:比对完当前的首尾字符后,需要同时丢弃左侧已比对字符和右侧已比对字符两个位置,因此下一层递归的有效长度应该比当前值减2,而非减1。如果只减1,会导致右侧边界永远无法向内移动,停留在最开始的位置。
- 递归基准可以更稳妥:你原本判断
length ==0返回真值的逻辑是正确的,但因为长度递减步长不对,容易出现长度为负数的边界问题,调整为length <=1时直接返回真值更可靠——不管是长度为0(偶数长度回文,全字符比对完成)还是长度为1(奇数长度回文,剩余中间单个字符天然匹配),都可以直接判定为回文,无需继续递归。
修正后的实现代码
int is_palindrome(char* p_string, int length) { // 递归基准:剩余区间长度不超过1时,必然是回文 if (length <= 1) { return 1; } // 比对首尾字符,不匹配直接判定不是回文 if (*p_string != *(p_string + length - 1)) { return 0; } // 向内收缩:左边界右移1位,有效长度减2(去掉左右两个已比对的字符) return is_palindrome(p_string + 1, length - 2); } int main() { char* p_string = "tacocat"; // 传入字符串实际可视长度,不计算末尾'\0' printf("%d", is_palindrome(p_string, 7)); return 0; }
补充说明
- 你之前在打印语句里输出的
p_string + length是当前区间尾部的下一个地址,并非尾部字符本身的地址,观察的时候容易和实际取字符的位置产生混淆。 - 只要调用时传入的
length是字符串的实际可视字符长度(不把末尾的'\0'算入),整个递归过程就不会出现越界访问的问题,不需要额外做空字符判断。
内容的提问来源于stack exchange,提问作者neko_lyn
相关产品推荐
相关产品推荐

