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.
This allocates 128 bytes on the stack, and uses the name
works
to refer to its address: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:You can write data to
works
, because it points to writable memory. You can't write data todoesnt
, 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 types
char[]
andchar *
are quite similar, so you are right about that. The difference lies in what happens when objects of the types are initialized. Your objectworks
, of typechar[]
, has 128 bytes of variable storage allocated for it on the stack. Your objectdoesnt
, of typechar *
, 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.The difference is in that
doesnt
points to memory that belongs to a string constant, and is therefore not writable.When you do this
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,
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 writablechar *
with string literals. The option is-Wwrite-strings
. You will get a warning that looks like this:The proper way to declare your
doesnt
pointer is as follows: