C语言中通过指针修改字符串触发总线错误的原因是什么?
问题原因拆解
1. 最初触发bus error的核心原因
你最初的代码里char *hello = "hello"定义的是字符串常量,这类字符串会被编译器放在进程的只读数据段,内存权限是只读,当你在strcopy里尝试向这个地址写入内容时,就会触发非法内存访问,报bus error或者segmentation fault。你这个点的判断是完全正确的。
2. 你的理解误区纠正
你关于「传递指针的值就不能在函数内解引用」的理解是错误的:
- 指针变量存储的值本身就是内存地址,C语言按值传递指针时,函数内部拿到的就是完整的内存地址值,只要这个地址指向的内存是可读写的,完全可以正常解引用操作。
- 你最初的代码报错和传递指针的值没有任何关系,完全是因为目标地址指向了只读内存区域。
3. 修改后代码出现编译器警告的原因
你把hello和world修改为栈上的字符数组char hello[] = "hello"是正确的选择,栈内存是可读写的。但调用strcopy时传&hello是多余且错误的:
- 数组名
hello本身在作为函数参数传递时,会自动退化为指向数组首元素的指针,类型就是char *,刚好匹配strcopy的参数要求。 &hello的类型是char (*)[6](指向长度为6的字符数组的指针),和strcopy要求的char *类型不匹配,所以编译器会抛出类型不兼容的警告。
正确的可运行代码
void strcopy(char *s, char *t) { while(*s++ = *t++) ; } int main(int argc, char *argv[]) { // 定义栈上字符数组,给足够的空间存储拷贝后的内容 char hello[10] = "hello"; char world[] = "world"; // 直接传数组名即可,自动退化为char* strcopy(hello, world); return 0; }
上述代码编译运行不会产生任何报错和警告。
内容的提问来源于stack exchange,提问作者456c526f
相关产品推荐
相关产品推荐

