char *和char []与strcpy()之间的区别

时间:2012-06-29 01:18:20

标签: c string char

过去几个小时我遇到了一个问题,虽然我明白了。这是我的麻烦:

void cut_str(char* entry, int offset) {
    strcpy(entry, entry + offset);
}

char  works[128] = "example1\0";
char* doesnt = "example2\0";

printf("output:\n");

cut_str(works, 2);
printf("%s\n", works);

cut_str(doesnt, 2);
printf("%s\n", doesnt);

// output:
// ample1
// Segmentation: fault

我觉得char * / char []有一些重要的东西,我没有来到这里。

3 个答案:

答案 0 :(得分:11)

区别在于doesnt指向属于字符串常量的内存,因此不可写。

当你这样做时

char  works[128] = "example1\0";

编译器将不可写字符串的内容复制到可写数组中。顺便说一下,\0不是必需的。

但是,当你这样做时,

char* doesnt = "example2\0";

编译器使指针指向不可写的内存区域。同样,编译器将插入\0

如果您使用gcc,可以让它警告您使用字符串文字初始化可写char *。选项为-Wwrite-strings。您将收到如下警告:

 warning: initialization discards qualifiers from pointer target type

声明doesnt指针的正确方法如下:

const char* doesnt = "example2\0";

答案 1 :(得分:4)

类型char[]char *非常相似,所以你是对的。不同之处在于初始化类型的对象时会发生什么。类型为works的对象char[]在堆栈上为其分配了128个字节的变量存储空间。您的对象doesnt,类型为char *在堆栈中没有存储空间。

C标准未指定存储doesnt字符串的确切位置,但很可能它存储在加载程序执行时加载的不可修改数据段中。这不是变量存储。因此,当您尝试改变它时会出现段错误。

答案 2 :(得分:3)

这会在堆栈上分配128个字节,并使用名称works来引用其地址:

char works[128];

所以works是指向可写内存的指针。

这会创建一个字符串文字,它位于只读内存中,并使用名称doesnt来引用其地址:

char * doesnt = "example2\0";

您可以将数据写入works,因为它指向可写内存。您无法将数据写入doesnt,因为它指向只读内存。

另外,请注意,您不必使用"\0"结束字符串文字,因为所有字符串文字都会隐式地在字符串末尾添加零字节。