C语言示例中传入char*参数可被正常修改的原因是什么?
C语言char*可写性问题解答
核心误区澄清
你对char*的认知存在偏差:char*本身从来不是只读类型,能否修改其指向的内容,完全由指针指向的内存区域的读写权限决定,和指针类型没有直接关系。
为什么修改sortString参数为char*后仍能正常运行
1. 函数参数的隐式退化规则
C语言中,数组作为函数参数传递时,会自动退化为指向数组首元素的指针。也就是说,你写的void sortString(char string[50])和void sortString(char *string)在编译器层面是完全等价的,改参数类型前后的代码没有本质区别,运行结果自然一致。
2. 指向的内存是可写的
你传入sortString的参数是buf,对应定义是char buf[50],这是在程序栈空间分配的临时数组,栈空间的内存默认是可读写的。即使退化为char*指针,指针指向的仍然是可读写的栈内存,修改内容当然不会报错。
为什么char *read = "Hello";修改会触发总线错误
这里触发错误的原因和char*类型无关,问题出在你指向的内容是字符串字面量:
- C标准明确规定,修改字符串字面量属于未定义行为。主流编译器实现中,所有双引号包裹的字符串字面量都会被存放在进程的
.rodata(只读数据段),该内存段的页权限被设置为只读,任何写入操作都会被操作系统拦截,触发异常(你遇到的总线错误、常见的段错误都是这类权限异常的表现)。 - 这种场景下只是
char*指针刚好指向了只读内存,并不是char*本身只能指向只读内存。
两个场景的核心差异对比
- 正常运行的场景:
char*指向栈/堆上分配的可读写内存(栈数组、malloc申请的内存都属于这类),具备写入权限。 - 报错的场景:
char*指向只读数据段的字符串字面量,不具备写入权限。
举个简单的验证例子:
// 写法1:指向字符串字面量,不可修改 char *ptr1 = "Hello"; // ptr1[0] = 'B'; 报错 // 写法2:栈数组,把字符串字面量内容拷贝到栈上,可修改 char ptr2[] = "Hello"; ptr2[0] = 'B'; // 正常运行,输出Bello
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

