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

C语言中字符串与字符加减运算的原理及异常结果疑问

解析C语言字符数组指针偏移的运算逻辑及异常情况

核心原理

在C语言中:

  • 字符数组名s是指向数组首元素的指针,s + n表示将指针向后偏移n个字符的内存位置(若n为负数则向前偏移)。
  • 字符类型char本质是ASCII值的整数存储,所以s[i]的运算实际是对字符的ASCII值进行计算。
  • printf("%s", ptr)会从ptr指向的内存位置开始输出字符,直到遇到字符串结束符\0为止。

第一个示例的运算过程

给定代码:

#include <stdio.h>

int main() {
    char s[] = "MANIPAL2022";
    printf("%s", s+s[4]-s[3]);

    return 0;
}

步骤1:拆解字符的ASCII值

数组s的每个字符及对应ASCII值(索引从0开始):

  • s[3] = 'I',ASCII值为73
  • s[4] = 'P',ASCII值为80

步骤2:计算偏移量

s[4] - s[3] = 80 - 73 = 7,因此表达式等价于s + 7。

步骤3:指针指向与输出

数组s的内容为:M A N I P A L 2 0 2 2 \0(索引0到11),s+7指向索引7的字符'2',从该位置开始输出直到\0,结果就是2022。


异常测试案例的原因分析

所有异常结果的核心原因:指针偏移后超出了字符数组的内存范围,触发了C语言的未定义行为(访问不属于当前数组的内存区域,内容完全随机)。

案例1:字符串"WESTHAM2022",原表达式s+s[4]-s[3]

  • s[3] = 'T'(ASCII 84),s[4] = 'H'(ASCII 72)
  • 偏移量:72 - 84 = -12,指针s-12指向数组首地址前12个字节的未知内存
  • 该区域没有有效的\0结束符,或全为不可打印字符,因此无输出。

案例2:调整为s+s[5]-s[3]

  • s[5] = 'A'(ASCII 65),偏移量:65 - 84 = -19
  • 指针进一步向前偏移,访问的内存内容完全随机,输出的!)�U 是该区域的随机二进制内容转成字符的结果。

案例3:调整为s+s[2]-s[3]

  • s[2] = 'S'(ASCII 83),偏移量:83 - 84 = -1
  • 指针指向数组首地址前1个字节,该位置恰好存储了ASCII值为57的字符'9'
  • 输出时先打印这个随机字符,接着继续打印数组的全部内容(因为数组内存是连续的),所以得到9WESTHAM2022。

内容的提问来源于stack exchange,提问作者Zeus Legend

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:55:25