Why do i first have to strcpy() before strcat()?

2019-01-11 03:00发布

问题:

Why does this code produce runtime issues:

char stuff[100];
strcat(stuff,"hi ");
strcat(stuff,"there");

but this doesn't?

char stuff[100];
strcpy(stuff,"hi ");
strcat(stuff,"there");

回答1:

strcat will look for the null-terminator, interpret that as the end of the string, and append the new text there, overwriting the null-terminator in the process, and writing a new null-terminator at the end of the concatenation.

char stuff[100];  // 'stuff' is uninitialized

Where is the null terminator? stuff is uninitialized, so it might start with NUL, or it might not have NUL anywhere within it.

In C++, you can do this:

char stuff[100] = {};  // 'stuff' is initialized to all zeroes

Now you can do strcat, because the first character of 'stuff' is the null-terminator, so it will append to the right place.

In C, you still need to initialize 'stuff', which can be done a couple of ways:

char stuff[100]; // not initialized
stuff[0] = '\0'; // first character is now the null terminator,
                 // so 'stuff' is effectively ""
strcpy(stuff, "hi ");  // this initializes 'stuff' if it's not already.


回答2:

In the first case, stuff contains garbage. strcat requires both the destination and the source to contain proper null-terminated strings.

strcat(stuff, "hi ");

will scan stuff for a terminating '\0' character, where it will start copying "hi ". If it doesn't find it, it will run off the end of the array, and arbitrarily bad things can happen (i.e., the behavior is undefined).

One way to avoid the problem is like this:

char stuff[100];
stuff[0] = '\0';      /* ensures stuff contains a valid string */
strcat(stuff, "hi ");
strcat(stuff, "there");

Or you can initialize stuff to an empty string:

char stuff[100] = "";

which will fill all 100 bytes of stuff with zeros (the increased clarity is probably worth any minor performance issue).



回答3:

Because stuff is uninitialized before the call to strcpy. After the declaration stuff isn't an empty string, it is uninitialized data.

strcat appends data to the end of a string - that is it finds the null terminator in the string and adds characters after that. An uninitialized string isn't gauranteed to have a null terminator so strcat is likely to crash.

If there were to intialize stuff as below you could perform the strcat's:

char stuff[100] = "";
strcat(stuff,"hi ");
strcat(stuff,"there");


回答4:

Strcat append a string to existing string. If the string array is empty, it is not going go find end of string ('\0') and it will cause run time error.

According to Linux man page, simple strcat is implemented this way:

   char*
   strncat(char *dest, const char *src, size_t n)
   {
       size_t dest_len = strlen(dest);
       size_t i;

       for (i = 0 ; i < n && src[i] != '\0' ; i++)
           dest[dest_len + i] = src[i];
       dest[dest_len + i] = '\0';

       return dest;
   }

As you can see in this implementation, strlen(dest) will not return correct string length unless dest is initialized to correct c string values. You may get lucky to have an array with the first value of zero at char stuff[100]; , but you should not rely on it.



回答5:

Also, I would advise against using strcpy or strcat as they can lead to some unintended problems.

Use strncpy and strncat, as they help prevent buffer overflows.



标签: c cstring