关于C语言回文检查程序反转字符串末尾自动追加'v'及未定义行为的技术咨询
解答回文检查程序的未定义行为问题
咱们一步一步拆解你遇到的所有困惑,核心原因是代码里存在明确的未定义行为,这才导致了各种奇怪的随机现象:
1. 为什么反转后的字符串末尾会自动出现'v'?
这是数组越界访问带来的随机内存值。看你的反转循环:
for(i=0;i<=j;i++){ reverse[i]=string[j-1-i]; }
这里的j是原字符串的有效字符数(比如输入"abc",j的值是3)。当i=j时,j-1-i = 3-1-3 = -1——你在访问string[-1],这是数组下标越界,属于C标准明确禁止的未定义行为。这个位置的内存不属于string数组,里面是随机的垃圾值,这次刚好是'v',换个环境运行可能会是其他字符甚至直接崩溃。
2. 移除回文检查后'v'就消失了?
还是未定义行为的随机性导致的。回文检查的代码会占用栈上的内存空间,当你保留这段代码时,string[-1]越界写入的位置刚好覆盖了栈上某个存着'v'的区域;移除回文检查后,栈的内存布局变了,越界写入的位置对应的内存值不是'v'了,所以现象就消失了。本质上都是越界访问带来的不可预测结果。
3. 代码里的未定义行为到底在哪里?
除了刚才说的数组下标越界访问string[-1],还有两个关键问题:
- 反转后的
reverse字符串没有添加字符串终止符'\0'。C语言中printf("%s")会一直读取内存直到遇到'\0',没有终止符的话,会继续读取reverse数组后面的栈内存,这也是未定义行为。 fflush(stdin)是未定义行为。C标准只规定fflush对输出流有效,输入流的fflush行为是未明确的,不同编译器可能有不同表现,甚至会引发问题。
4. 为什么反转后的字符串有输出,而不是预期的空?
你以为'\0'会被放到反转字符串的开头,但实际上你的逻辑错了:原字符串的'\0'在string[j]的位置,而你的循环里并没有把'\0'写入reverse。反而因为没有加终止符,printf("%s")会从reverse[0]开始读,把你写入的反转字符、越界写入的垃圾值,直到栈里某个随机的'\0'都打印出来,所以会有内容输出,而不是空。
修正后的代码示例
把循环条件改成i < j,并且手动给reverse添加终止符,同时去掉不必要的fflush(stdin):
#include<stdio.h> int main(){ int i,j; char string[100],reverse[100]; printf("enter a string:\n"); scanf("%s",string); // 计算字符串有效字符数(不含'\0') for(j=0;string[j]!='\0';j++); // 反转字符串,只处理有效字符 for(i=0;i<j;i++){ reverse[i]=string[j-1-i]; } // 必须添加字符串终止符 reverse[j] = '\0'; printf("%s ,%d, %d\n",reverse,j,i); int is_palindrome=1; for( i=0;i<j;i++){ if(string[i]!=reverse[i]){ is_palindrome=0; break; } } if(is_palindrome){ printf("is palindrome"); } else{ printf("is not palindrome"); } return 0; }
内容的提问来源于stack exchange,提问作者Coder Manish
相关产品推荐
相关产品推荐

