为何在main()中调用reverse()输出12345,在itoa()末尾调用则输出54321?
问题解析:itoa函数中reverse调用位置导致输出差异的原因
用户代码
#include <stdio.h> #include <string.h> void itoa(long n, char *s); void reverse(char *s); int main() { int n = 12345; char s[10]; itoa(n, s); printf("%s\n", s); return 0; } void itoa(long n, char *s) { int i; while (n != 0) { *s++ = n % 10 + '0'; n /= 10; } *s = '\0'; reverse(s); } void reverse(char *s) { int i, temp, len = strlen(s); for (i = 0; i < len / 2; i++) { temp = s[len - 1 - i]; s[len - 1 - i] = s[i]; s[i] = temp; } }
用户疑问
为何将reverse()函数放在main()中调用时,程序输出12345;而将reverse()作为itoa()定义的最后一条语句调用时,程序输出54321?两次调用均传递指针作为参数,预期输出应一致。
原因解析
核心问题出在itoa函数里的指针偏移:
- 在
itoa的循环中,*s++ = n%10 + '0'每执行一次,指针s就会向后移动一个字节。等循环结束并执行*s = '\0'后,此时的s已经指向了字符串末尾的空字符'\0'位置,不再是传入函数的数组起始地址。 - 这时候调用
reverse(s),相当于把指向空字符串的指针传进函数——strlen(s)返回0,反转的for循环根本不会执行。而之前循环已经把数字按5、4、3、2、1的顺序存在数组起始位置到s当前位置之前,所以程序直接输出未反转的54321。 - 如果在
main()里调用reverse(s),这里的s是数组起始地址,指向itoa填充好的"54321"字符串,strlen能正确获取长度5,反转后就得到12345。
修正方案
要让itoa内部调用reverse也能得到正确结果,只需在itoa函数开头保存数组的起始指针,最后传入这个起始指针给reverse:
void itoa(long n, char *s) { char *start = s; // 保存数组起始地址 while (n != 0) { *s++ = n % 10 + '0'; n /= 10; } *s = '\0'; reverse(start); // 传入起始地址而非偏移后的指针 }
内容的提问来源于stack exchange,提问作者materia-nigra
相关产品推荐
相关产品推荐

