使用指针时为何出现总线错误(bus error)?
问题拆解:字符串字面量的只读属性与运算符优先级
嘿,这个问题其实戳中了C语言里两个容易踩坑的点:字符串字面量的内存特性,还有运算符的优先级/结合性,我来给你一步步理清楚:
为什么++*str会触发总线错误?
- 首先,当你写
char *str = "test";时,"test"是字符串字面量。在C语言的实现里,这类字符串会被编译器放在程序的只读数据段(比如常见的.rodata段)中,这块内存区域是受操作系统内存保护的,不允许执行写入操作。 - 再看
++*str的执行逻辑:前缀++和*的优先级相同,结合性是从右到左,所以这个表达式等价于++(*str)——先通过*str解引用指针,拿到第一个字符't',然后尝试对这个字符执行自增操作(把't'改成'u')。但因为这个字符所在的内存是只读的,写入操作直接触发了内存保护机制,也就出现了你看到的zsh: bus error。
为什么*++str就能正常运行?
*++str的运算顺序完全不同:前缀++先作用于指针str本身,把指针向后移动一个内存位置(从指向't'变成指向'e'),然后再通过*解引用这个更新后的指针,读取对应的字符'e'并输出。整个过程我们只是读取只读内存里的内容,没有尝试修改任何数据,所以不会触发内存错误。
额外小提示
如果确实需要修改字符串的内容,你应该把字符串字面量复制到可写的内存区域里,比如用数组声明:
char str[] = "test"; printf("%c", ++*str); // 这时候会正常输出'u'
这样字符串会被存储在栈上(属于可写内存),修改操作就合法了。
内容的提问来源于stack exchange,提问作者Liwinux
相关产品推荐
相关产品推荐

