C语言指针混合表达式运算顺序解析:以str+str[4]-*str为例
C语言中表达式
str+str[4]-*str的执行逻辑详解 前置运算规则
C语言表达式计算严格遵循优先级从高到低、同优先级从左到右结合的规则:
- 下标访问
[]、解引用*属于最高优先级梯队,优先级远高于二元加法+、减法- - 二元加减属于同优先级,执行左结合,即按顺序从左到右计算
- 指针和整数做加减时,偏移单位是指针指向的元素长度;
char*类型的元素长度为1字节,和单字节的char ASCII值做运算时,偏移量天然匹配。
表达式分步计算流程
首先列出字符串char str[50] = "hello \0 worl\bd";的前13个存储位置的值(数组未被初始化覆盖的位置全部为\0,作为字符串终止标记):
| 数组索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 存储字符 | h | e | l | l | o | 空格 | \0 | 空格 | w | o | r | \b | d |
| ASCII值 | 104 | 101 | 108 | 108 | 111 | 32 | 0 | 32 | 119 | 111 | 114 | 8 | 100 |
按照优先级计算str + str[4] - *str的步骤:
- 先完成所有高优先级的取值操作
因为[]和*优先级远高于加减,必须先把这两个子表达式的值算出来:str[4]等价于*(str+4),取到索引4处的字符o,参与算术运算时自动转换为ASCII整数值111*str等价于*(str+0),取到索引0处的字符h,参与算术运算时自动转换为ASCII整数值104
这一步根本不存在错误推演里“先算str+str”的逻辑——因为加减的优先级更低,不可能抢在取值操作前面计算。
- 按左结合规则完成加减运算
两个加减为同优先级,从左到右依次计算:- 先算
str + str[4]:str是指向数组首地址的char*指针,加上整数值111,相当于指针从首地址向后偏移111个char长度 - 再将上一步的结果减去
*str的值104:相当于从刚才的偏移位置回退104个char长度
因为char是单字节类型,最终净偏移量为111 - 104 = 7,也就是最终指针等价于str + 7,指向数组索引7的位置(也就是\0终止符之后的第一个空格位置)。
指针偏移的净效果只和整数部分的最终差值有关,和加减的先后顺序无关,这里无论怎么调整计算顺序,最终都是指向索引7的位置。
- 先算
完整输出效果对应
第一行printf的输出
printf("\n %s ",str); 打印字符串时,%s遇到第一个\0(索引6位置)就会停止,实际输出换行符、空格、hello加空格,视觉上呈现hello的效果。
第二行printf的输出
printf("%s \n",str+str[4]-*str); 从索引7的位置开始打印字符串:
- 依次输出索引7的空格、
w、o、r - 遇到索引11位置的退格符
\b:光标向前回退1格,覆盖掉刚才输出的r的位置 - 继续输出索引12位置的
d,直接替换原来r所在的位置,最终视觉上看到的字符串是word - 直到遇到后续默认填充的
\0停止打印,加上格式控制里的尾随空格,构成后半段输出
两部分输出拼接后,终端实际呈现的效果就是hello word,和运行结果完全匹配。
之前推演的核心误区
之前的计算步骤完全颠倒了运算符优先级:
- 误以为二元加号的优先级高于
[]和*,才会推导出“先算str加str、再偏移4位解引用”的错误逻辑 - 实际上
[]和*是最高优先级的运算,必须先完成取值、拿到字符对应的ASCII整数值,才能参与后续的指针加减运算。
内容的提问来源于stack exchange,提问作者arturvruffer
相关产品推荐
相关产品推荐

