Jin Jin - 2 months ago 4x
C Question

What's wrong with this function that shortens strings?

I have defined a function in C which shortens long strings to fixed size and prints the shortened string. The function goes like this:

void fit(char *str,unsigned int size) // shorten long strings to fixed size, "size" and prints the shortened string.
if ( strlen(str) > size)
str[size] = '\0';
printf("%s", str); // prints the shortened string

If I run this function, the compilers points out no warning nor error but the execution stops. What part of the code makes the execution stop?

#include <stdio.h>
#include <string.h>

void fit(char *str, unsigned int size);

int main(void)
fit("Hello People!!", 6);

void fit(char *str,unsigned int size)
if ( strlen(str) > size)
str[size] = '\0';
printf("%s", str);

Dai Dai

In standard C and C++, string literals ("these") are read-only.

Typically these are located in read-only memory. By writing to str in your specific example your program attempts write to write-protected memory, which is disallowed by the OS (or the runtime, if applicable) which causes an abnormal program termination. If you were writing C++ the compiler might complain that you were passing a const char* to a function that accepted a non-const argument.

You have four options:

  1. Tell the compiler to put the `"Hello People!!" string in a writable data area instead of write-protected data when building or initializing the program

  2. Use an OS-specific command to make the memory area writable (have fun!)

  3. Copy the string to a mutable buffer before you modify it.

  4. Use char str[] = "Hello People!!"; - this is basically the same as option 3 but the compiler does it for you. Be careful when leaving scope, however.

Note that inserting null characters into a string buffer as a means of shortening a string can be a bad idea because it hides the extra space in the allocated buffer. Generally you should treat strings as immutable, and if you want to be efficient by re-using strings in a copy-on-write fashion then use start/end pairs that point to an extant buffer instead of relying on null-termination.