后置递增指针间赋值的运算顺序及语法解析
关于C语言
*buf++ = *event_str++;的执行顺序与语法疑问 作为C语言新手,我在学习树莓派Pico的示例代码时,对*buf++ = *event_str++;这句语法完全摸不着头脑,想搞清楚它底层的运算顺序,以及相关的语法规则。
以下是相关代码片段:
static const char *gpio_irq_str[] = {"LEVEL_LOW", // 0x1 "LEVEL_HIGH", // 0x2 "EDGE_FALL", // 0x4 "EDGE_RISE" // 0x8}; void gpio_event_string(char *buf, uint32_t events) { for (uint i = 0; i < 4; i++) { uint mask = (1 << i); if (events & mask) { const char *event_str = gpio_irq_str[i]; while (*event_str != '\0') { *buf++ = *event_str++; } events &= ~mask; if (events) { *buf++ = ','; *buf++ = ' '; } } } *buf++ = '\0'; }
假设当i=3时(events & mask) == 1(对应"EDGE_RISE"场景),我自己猜测的执行顺序是:
- 获取event_str指针存储的地址
- 获取buf指针存储的地址
- 取出event_str指向地址里的字符(比如第一个字符'E')
- 把这个字符复制到buf指向的内存地址
- 同时把event_str和buf的地址各加1(指向下一个内存位置)
- 重复上述步骤,直到遇到'\0'结束
但我有几个疑问:
- 我原本以为
*event_str是取指针指向的字符值,为什么*event_str++是递增指针的地址,而不是修改指针指向的值? - 怎么通过语法判断
++是作用在指针本身,还是指针指向的值? - 有没有讲解这类字符串复制语法的书籍或参考资料?
一、*buf++ = *event_str++;的实际执行顺序
你的猜测基本正确,更严谨的执行逻辑是:
- 先计算
*event_str:取出当前event_str指针指向的字符值 - 计算
*buf:定位到当前buf指针指向的内存位置 - 将步骤1取出的字符赋值给步骤2的内存位置
- 执行
event_str++:把event_str指针的地址加1(因为是char指针,所以偏移1个字节,指向下一个字符) - 执行
buf++:把buf指针的地址加1,准备存储下一个字符
这里关键是:C语言中后缀++的优先级高于*(解引用),且后缀++的规则是先返回变量当前的值,再对变量进行自增。所以*event_str++等价于*(event_str++)——先通过event_str的当前地址取字符,再把指针往后挪一位。
二、怎么判断++作用在指针还是指向的值?
核心看运算符的优先级和括号:
*ptr++:后缀++优先级更高,等价于*(ptr++),先返回ptr的当前地址取值,再让指针自增,最终是指针本身被递增。(*ptr)++:括号改变了优先级,先解引用ptr得到指向的值,再对这个值做自增,最终是指针指向的值被修改。++*ptr:前缀++和*优先级相同,结合性从右到左,等价于++(*ptr),同样是修改指针指向的值。
简单总结:没有括号的后缀++,作用对象一定是指针本身;加了括号或者用前缀++,才会作用在指针指向的值上。
三、相关参考资料
- 《C程序设计语言》(K&R):C语言的经典入门书,对指针、运算符优先级这类基础语法讲得非常透彻,这类字符串复制的写法在书中有不少示例。
- 《C Primer Plus》:适合新手的入门教材,对指针和运算符的讲解更细致,有大量实例帮助理解。
- C语言标准文档(如ISO/IEC 9899):如果想抠底层细节,标准里明确规定了运算符的优先级和执行顺序,适合有一定基础后查阅。
内容的提问来源于stack exchange,提问作者topher217
相关产品推荐
相关产品推荐

