这个程序说明了我的问题。
#include "stdio.h"
#include "string.h"
void first_try() // segmentation fault
{
size_t numc = 1;
char *dest = "i "; // this is bad? i need to declare character array first? why?
char *src = "lone wolf c program\n";
memcpy(dest, src, numc);
printf("%s", dest);
}
void second_try() // works
{
size_t numc = 1;
char dest[24] = "i get overwritten";
char *src = "lone wolf c program\n";
memcpy(dest, src, 20);
printf("%s", dest);
}
int main(void)
{
//first_try(); // run-time error
second_try();
}
为什么... first_try()
方法导致分段故障错误?
上下文
// feel free to ignore this context
我还是个c语言编程新手。我去了 https:/www.devdocs.io 并看了一下api的 memcpy()
.我的本能是立即写 first_try()
. 我不明白这两者之间的区别 dest
变量的每个函数。它们不是都包含有效的地址值吗?
我在一个 "字符串作为指针 "的博客中看到 "包含字符串的字符数组必须已经存在"。很显然,只写 char *dest = "string";
编译,但比写 char buf[] = "string";
与一个可以传递的后续ptr。char *dest = &buf;
. 我想知道这一切的 "为什么"。
在C语言中,所有的字面字符串(如你的 "i "
)实际上是一个不可修改的数组,包含了字符串中的字符,加上null-terminator。
试图修改一个字面字符串会导致 未定义行为.
当你使用一个指针作为 dest
char *dest = "i ";
你让指针指向字符串的三元素数组的第一个元素。"i "
.
当你把它作为一个目的地,用于 memcpy
你试图修改这个不可修改数组的内容,会导致未定义的行为和你的崩溃。
这就是为什么你通常应该使用 const
当定义这样的指针时。
const char *dest = "i ";
当你使用一个数组作为目标数组时, 它被分配在你的程序的一个可写的内存中 你可以随意修改它.
但请确保目标数组足够大,以容纳完整的源字符串。包括 的null-terminator。否则,您的 memcpy
调用将写出所分配内存的边界,你将再次拥有 未定义行为.