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值为73s[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
相关产品推荐
相关产品推荐

