Strings

Working with strings in C. String manipulation functions from the `string.h` library.


String Copying in C: strcpy and strncpy

Understanding String Copying in C

In C, strings are represented as arrays of characters, terminated by a null character ('\0'). Unlike many higher-level languages, C doesn't have a built-in string object or a direct assignment operator for copying strings. Instead, you need to copy the characters one by one until you encounter the null terminator.

The strcpy Function

The strcpy function (declared in string.h) is a standard library function used to copy one string to another. Its prototype is:

char *strcpy(char *destination, const char *source);

It copies the string pointed to by source (including the null terminator) to the buffer pointed to by destination. The function returns a pointer to the destination string.

Example:

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

int main() {
    char source[] = "Hello, world!";
    char destination[20]; // Make sure the destination buffer is large enough

    strcpy(destination, source);

    printf("Source string: %s\n", source);
    printf("Destination string: %s\n", destination);

    return 0;
} 

Explanation:

  • We include the necessary header files (stdio.h and string.h).
  • We define a source string source and a destination buffer destination. It's crucial that destination is large enough to hold the contents of source, including the null terminator.
  • strcpy(destination, source); copies the string "Hello, world!" from source to destination.
  • The printf statements display the contents of both strings.

Buffer Overflow and strcpy

The main problem with strcpy is that it doesn't perform any bounds checking. If the source string is larger than the destination buffer, strcpy will write past the end of the destination buffer, leading to a buffer overflow. This can overwrite adjacent memory, causing program crashes, unexpected behavior, or even security vulnerabilities (allowing attackers to inject malicious code).

Example of a Buffer Overflow:

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

int main() {
    char source[] = "This is a very long string that will overflow the destination buffer.";
    char destination[10]; // Destination buffer is too small

    strcpy(destination, source); // Potential buffer overflow!

    printf("Source string: %s\n", source);
    printf("Destination string: %s\n", destination); // Might print garbage or crash

    return 0;
} 

In this example, destination is only 10 bytes long, but source is much longer. strcpy will write past the end of destination, causing a buffer overflow. The results are unpredictable.

The strncpy Function: A Safer Alternative

The strncpy function (also in string.h) is a safer alternative to strcpy. It limits the number of characters copied.

char *strncpy(char *destination, const char *source, size_t n);

It copies at most n characters from the string pointed to by source to the buffer pointed to by destination. If the length of source is less than n, strncpy copies the entire string source and adds null terminators until n characters have been written. If the length of source is greater than or equal to n, strncpy copies only the first n characters, and the resulting string in destination might not be null-terminated. The function returns a pointer to the destination string.

Example Using strncpy:

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

int main() {
    char source[] = "Hello, world!";
    char destination[10];

    strncpy(destination, source, sizeof(destination) - 1); // Copy at most 9 characters

    destination[sizeof(destination) - 1] = '\0'; // Manually add null terminator to ensure it's a valid string

    printf("Source string: %s\n", source);
    printf("Destination string: %s\n", destination);

    return 0;
} 

Explanation:

  • strncpy(destination, source, sizeof(destination) - 1); copies at most sizeof(destination) - 1 (which is 9 in this case) characters from source to destination. This prevents a buffer overflow.
  • destination[sizeof(destination) - 1] = '\0'; is crucial. Since strncpy might not null-terminate the destination string, we manually add the null terminator at the end. This ensures that destination is a valid C string.

Best Practices and Considerations

  • Always use strncpy instead of strcpy to prevent buffer overflows.
  • Always ensure that the destination buffer is large enough to hold the copied string (or at least the first n characters if using strncpy).
  • When using strncpy, always manually add a null terminator to the destination buffer after the copy operation to ensure it's a valid string.
  • Consider using more modern and safer string handling functions (like those available in C11's Annex K) if available in your environment.
  • Always be aware of the size of your buffers and the length of the strings you are copying.