You can use the =
operator to copy integers, but you cannot use the =
operator to copy strings in C. Strings in C are represented as arrays of characters with a terminating null-character, so using the =
operator will only save the address (pointer) of a string.
#include <stdio.h>
int main(void) {
int a = 10, b;
char c[] = "abc", *d;
b = a; /* Integer is copied */
a = 20; /* Modifying a leaves b unchanged - b is a 'deep copy' of a */
printf("%d %d\\n", a, b); /* "20 10" will be printed */
d = c;
/* Only copies the address of the string -
there is still only one string stored in memory */
c[1] = 'x';
/* Modifies the original string - d[1] = 'x' will do exactly the same thing */
printf("%s %s\\n", c, d); /* "axc axc" will be printed */
return 0;
}
The above example compiled because we used char *d
rather than char d[3]
. Using the latter would cause a compiler error. You cannot assign to arrays in C.
#include <stdio.h>
int main(void) {
char a[] = "abc";
char b[8];
b = a; /* compile error */
printf("%s\\n", b);
return 0;
}
strcpy()
To actually copy strings, [strcpy()](<http://linux.die.net/man/3/strcpy>)
function is available in string.h
. Enough space must be allocated for the destination before copying.
#include <stdio.h>
#include <string.h>
int main(void) {
char a[] = "abc";
char b[8];
strcpy(b, a); /* think "b special equals a" */
printf("%s\\n", b); /* "abc" will be printed */
return 0;
}
snprintf()
To avoid buffer overrun, [snprintf()](<http://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html>)
may be used. It is not the best solution performance-wise since it has to parse the template string, but it is the only buffer limit-safe function for copying strings readily-available in standard library, that can be used without any extra steps.
#include <stdio.h>
#include <string.h>
int main(void) {
char a[] = "012345678901234567890";
char b[8];
#if 0
strcpy(b, a); /* causes buffer overrun (undefined behavior), so do not execute this here! */
#endif
snprintf(b, sizeof(b), "%s", a); /* does not cause buffer overrun */
printf("%s\\n", b); /* "0123456" will be printed */
return 0;
}
strncat()
A second option, with better performance, is to use [strncat()](<http://pubs.opengroup.org/onlinepubs/9699919799/functions/strncat.html>)
(a buffer overflow checking version of strcat()
) - it takes a third argument that tells it the maximum number of bytes to copy:
char dest[32];
dest[0] = '\\0';
strncat(dest, source, sizeof(dest) - 1);
/* copies up to the first (sizeof(dest) - 1) elements of source into dest,
then puts a \\0 on the end of dest */
Note that this formulation use sizeof(dest) - 1
; this is crucial because strncat()
always adds a null byte (good), but doesn’t count that in the size of the string (a cause of confusion and buffer overwrites).
Also note that the alternative — concatenating after a non-empty string — is even more fraught. Consider:
char dst[24] = "Clownfish: ";
char src[] = "Marvin and Nemo";
size_t len = strlen(dst);
strncat(dst, src, sizeof(dst) - len - 1);
printf("%zu: [%s]\\n", strlen(dst), dst);
The output is:
23: [Clownfish: Marvin and N]