c - 为什么不能使用指针更改字符?
问题描述
最近我得到了一本 C 编程语言书。在第 95 页有一个 strcpy 函数的实现。
void strcopy(char *s, char *t) {
while(*s++ = *t++)
;
}
int main(int argc, char *argv[]) {
char *hello = "hello";
char *world = "world";
strcopy(hello, world);
return 0;
}
我试图自己实现它,但是在(成功)编译之后
gcc -o c_lang c_programming_lang_exercises.c
并尝试运行它
./c_lang
我收到以下错误消息:
zsh: bus error
我尝试了不同的实现,但不知何故这对我不起作用。
也许有人知道为什么?
谢谢您的帮助 :)
编辑:出于我自己的理解,如果我错了,请纠正我。在函数中调用“strcopy(hello, world);” 我在这里传递指针本身的值,所以我用这样的东西调用函数:strcopy(0x123a4,0x234859b)。现在 C 不认为 this 是变量,因此它的值被复制并传递给函数。在 strcopy 函数本身中我不能取消引用它,因为我只是得到指针的值。
我应该做的是传递地址,指针引用,以便我可以取消引用 strcopy 函数中的值并访问正确的内存地址。
另一个错误可能在我声明的主函数char *hello = "hello"
中,据我所知,它称为字符串常量,因此不可修改。
所以,如果我的假设是正确的,下面的代码应该可以工作:
void strcopy(char *s, char *t) {
//code goes here...
}
int main(int stringc, char *argv[]) {
char hello[] = "hello";
char world[] = "world";
strcopy(&hello, &world);
return 0;
}
它有效,但我收到以下编译器警告:
incompatible pointer types passing 'char (*)[6]' to parameter of type 'char **' [-Wincompatible-pointer-types]
strcopy(&hello, &world);
解决方案
C 在类型方面做出了非常糟糕的让步,这与历史原因有关。
在main()
中,您将字符串声明为:
char *hello = "hello";
您应该做的是将警告级别调高并重新编译。问题是这"hello"
是一个字符串文字——它不能被修改。它应该声明为:
const char *hello = "hello";
(打开警告会告诉你这一点。)
因此,您试图将字符复制到只读内存中,这在现代处理器和现代编译器上是不允许的——它会产生访问冲突。Zsh 为你抱怨。
相反,请确保您对从只读内存复制的本地数组具有写访问权限:
char hello[] = "hello";
是的,这产生了一个本地的、可变的数组,它有六个字符长(五个字符用于单词“hello”加上一个用于空终止符)并从只读内存自动初始化。
这是在 C 中声明的东西经常使初学者感到困惑的微妙症结之一:
const char * s = "Hello world!";
— 指向 ROM 的指针char s[] = "Hello world!";
— 从 ROM 初始化的本地可变数组
而已!
推荐阅读
- time-series - 为什么 Python statsmodels...SARIMAX.predict 不起作用?
- python - 当我还下载了 Visual Studio 时,如何在我的 Windows 中安装 dlib?此错误开始出现
- javascript - 从 javascript [spotify auth] 中的弹出窗口获取访问令牌 url
- javascript - 我正在尝试添加手风琴,但它没有打开
- c - 数组索引中的变量不改变其值
- java - 双向链表排序:一个数据显示两次,一个数据丢失
- java - Spring 多对多关系 JpaObjectRetrievalFailureException
- mysql - 如何将 Eloquent 查询转换为 Adonis lucid?
- javascript - MobX 'this' 在 setter 动作中未定义
- python - 如何解决此 python 迁移错误