简体   繁体   中英

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.

The difference is in that doesnt points to memory that belongs to a string constant, and is therefore not writable.

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.

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.

If you are using gcc , you can have it warn you about initializing writable char * with string literals. The option is -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:

const char* doesnt = "example2\0";

The types char[] and char * are quite similar, so you are right about that. 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. Your object doesnt , of type char * , has no storage on the stack.

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. 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:

char works[128];

So works is a pointer to writable memory.

This creates a string literal, which is in read-only memory, and uses the name doesnt to refer to its address:

char * doesnt = "example2\0";

You can write data to works , because it points to writable memory. You can't write data to doesnt , because it points to read-only memory.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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