简体   繁体   English

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

[英]difference between char* and char[] with strcpy()

I've been having trouble the past couple hours on a problem I though I understood. 过去几个小时我遇到了一个问题,虽然我明白了。 Here's my trouble: 这是我的麻烦:

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

I feel like there's something important about char*/char[] that I'm not getting here. 我觉得char * / char []有一些重要的东西,我没有来到这里。

The difference is in that doesnt points to memory that belongs to a string constant, and is therefore not writable. 不同之处在于,它doesnt指向属于字符串常量的内存,因此不可写。

When you do this 当你这样做

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

the compiler copies the content of a non-writable string into a writable array. 编译器将不可写字符串的内容复制到可写数组中。 \\0 is not required, by the way. 顺便说一句, \\0不是必需的。

When you do this, however, 但是,当你这样做时,

char* doesnt = "example2\0";

the compiler leaves the pointer pointing to a non-writable memory region. 编译器使指针指向不可写的内存区域。 Again, \\0 will be inserted by compiler. 同样, \\0将由编译器插入。

If you are using gcc , you can have it warn you about initializing writable char * with string literals. 如果你正在使用gcc ,你可以让它警告你用字符串文字初始化可写char * The option is -Wwrite-strings . 选项是-Wwrite-strings You will get a warning that looks like this: 您将收到如下警告:

 warning: initialization discards qualifiers from pointer target type

The proper way to declare your doesnt pointer is as follows: 声明你的正确方法doesnt指针如下:

const char* doesnt = "example2\0";

The types char[] and char * are quite similar, so you are right about that. char[]char *类型非常相似,所以你是对的。 The difference lies in what happens when objects of the types are initialized. 不同之处在于初始化类型的对象时会发生什么。 Your object works , of type char[] , has 128 bytes of variable storage allocated for it on the stack. 您的对象works ,类型为char[] ,在堆栈上为其分配了128个字节的变量存储。 Your object doesnt , of type char * , has no storage on the stack. 你的目标doesnt ,类型的char *具有堆栈上没有存储。

Where exactly the string of doesnt is stored is not specified by the C standard, but most likely it is stored in a nonmodifiable data segment loaded when your program is loaded for execution. 确切位置在哪里串doesnt存储不是由C标准的规定,但最有可能被存储在当你的程序被加载执行加载一个不可更改的数据段。 This isn't variable storage. 这不是变量存储。 Thus the segfault when you try to vary it. 因此,当您尝试改变它时的段错误。

This allocates 128 bytes on the stack, and uses the name works to refer to its address: 这在堆栈上分配128个字节,并使用名称works来引用其地址:

char works[128];

So works is a pointer to writable memory. 因此, works是指向可写内存的指针。

This creates a string literal, which is in read-only memory, and uses the name doesnt to refer to its address: 这将创建一个字符串文字,它位于只读内存中,并使用名称doesnt来引用其地址:

char * doesnt = "example2\0";

You can write data to works , because it points to writable memory. 您可以将数据写入works ,因为它指向可写内存。 You can't write data to doesnt , because it points to read-only memory. 您不能将数据写入doesnt ,因为它指向只读内存。

Also, note that you don't have to end your string literals with "\\0" , since all string literals implicitly add a zero byte to the end of the string. 另请注意,您不必使用"\\0"结束字符串文字,因为所有字符串文字都会隐式地在字符串末尾添加一个零字节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM