You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言字符串交换时出现异常行为的原因排查

问题分析与解决方案

核心错误原因

  1. 数组越界引发未定义行为
    你的s2是用char s2[] = "Banned Birds";初始化的,数组实际长度是13(包含末尾的'\0',索引范围0-12)。但循环的max值取了两个字符串长度的最大值+1(也就是16),导致循环执行到i=15。此时i=13、14、15时访问s2[i]属于数组越界,读取和写入的都是栈上的随机内存,会破坏相邻变量或数组的内容,这是C语言中严重的未定义行为,最终导致s1的内容被意外篡改。

  2. 提前交换'\0'导致字符串截断
    当i=12时,s2[12]是字符串结束符'\0',交换后s1[12]变成'\0'。此时s1从索引12开始就被标记为结束,后续字符交换虽然执行,但puts输出时遇到'\0'就会停止。再加上后续越界写入破坏了内存,最终造成s1输出异常。

  3. 错误的交换逻辑
    逐个字符交换的方式只适用于长度完全相同的字符串。对于长度不同的字符串,短字符串的'\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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 13:55:02