C语言字符串交换时出现异常行为的原因排查
问题分析与解决方案
核心错误原因
数组越界引发未定义行为
你的s2是用char s2[] = "Banned Birds";初始化的,数组实际长度是13(包含末尾的'\0',索引范围0-12)。但循环的max值取了两个字符串长度的最大值+1(也就是16),导致循环执行到i=15。此时i=13、14、15时访问s2[i]属于数组越界,读取和写入的都是栈上的随机内存,会破坏相邻变量或数组的内容,这是C语言中严重的未定义行为,最终导致s1的内容被意外篡改。提前交换
'\0'导致字符串截断
当i=12时,s2[12]是字符串结束符'\0',交换后s1[12]变成'\0'。此时s1从索引12开始就被标记为结束,后续字符交换虽然执行,但puts输出时遇到'\0'就会停止。再加上后续越界写入破坏了内存,最终造成s1输出异常。错误的交换逻辑
逐个字符交换的方式只适用于长度完全相同的字符串。对于长度不同的字符串,短字符串的'\0'会提前截断长字符串,同时越界访问会引发未定义行为,完全达不到交换的目的。
正确的字符串交换方案
方案1:交换指针(最简单高效)
如果允许修改指针指向,直接交换指针是最优解,不需要修改数组本身的内容:
#include <stdio.h> #include <string.h> void swap(char** s1, char** s2) { char* temp = *s1; *s1 = *s2; *s2 = temp; } int main() { char s1[] = "Banned Playbird" ; char s2[] = "Banned Birds" ; char* p1 = s1; char* p2 = s2; swap(&p1, &p2); printf("s1 is now: ") ; puts(p1) ; printf("s2 is now: ") ; puts(p2) ; return 0 ; }
方案2:交换数组内容(确保空间足够)
如果必须修改数组内容,需要先确保两个数组的长度都能容纳对方的字符串,比如定义足够大的固定长度数组:
#include <stdio.h> #include <string.h> void swap(char* s1, char* s2, size_t max_len) { char temp[max_len]; strcpy(temp, s1); strcpy(s1, s2); strcpy(s2, temp); } int main() { // 定义足够大的数组,确保能容纳另一个字符串 char s1[50] = "Banned Playbird" ; char s2[50] = "Banned Birds" ; swap(s1, s2, 50); printf("s1 is now: ") ; puts(s1) ; printf("s2 is now: ") ; puts(s2) ; return 0 ; }
这里用标准库函数strcpy直接复制整个字符串,避免了逐个字符交换的问题,同时确保数组有足够空间。
总结
- 不要直接逐个交换不同长度字符串的字符,这会导致
'\0'提前截断和数组越界。 - 优先使用指针交换的方式,简单高效且无内存问题。
- 如果必须修改数组内容,确保数组有足够的空间容纳另一个字符串,使用标准库函数完成复制。
内容的提问来源于stack exchange,提问作者M.B.
相关产品推荐
相关产品推荐

