strncpy, strncpy_s
| Definido en el encabezado <string.h>
|
||
char* strncpy( char* dest, const char* src, size_t count );
|
(1) | (hasta C99) |
char* strncpy( char* restrict dest, const char* restrict src, size_t count );
|
(desde C99) | |
errno_t strncpy_s( char* restrict dest, rsize_t destsz,
const char* restrict src, rsize_t count );
|
(2) | (desde C11) |
count caracteres del arreglo de caracteres apuntado por src (incluyendo el carácter nulo de terminación, pero no ninguno de los caracteres que siguen al carácter nulo) al arreglo de caracteres apuntado por dest.count antes de que se copiara todo el arreglo src, el arreglo de caracteres resultante no termina en nulo.src, no se alcanza count, se escriben caracteres nulos adicionales en dest hasta que se haya escrito un total de count caracteres.dest o src no es un puntero a un arreglo de caracteres (incluyendo si dest o src es un puntero nulo), si el tamaño del arreglo apuntado por dest es menor que count, o si el tamaño del arreglo apuntado por src es menor que count y no contiene un carácter nulo.count, se detiene después de escribir el carácter nulo de terminación (si no había nulo en la fuente, escribe uno en dest[count] y luego se detiene). Además, los siguientes errores se detectan en tiempo de ejecución y llaman a la función manejador de restricciones instalada actualmente:
srcodestes un puntero nulodestszes cero o mayor que RSIZE_MAXcountes mayor que RSIZE_MAXcountes mayor o igual quedestsz, perodestszes menor o igual questrnlen_s(src, count), en otras palabras, ocurriría truncamiento- ocurriría superposición entre las cadenas fuente y destino
dest < strnlen_s(src, destsz) <= destsz; en otras palabras, un valor erróneo de destsz no expone el inminente desbordamiento de búfer. El comportamiento no está definido si el tamaño del arreglo de caracteres apuntado por src < strnlen_s(src, count) < destsz; en otras palabras, un valor erróneo de count no expone el inminente desbordamiento de búfer.strncpy_s solo está garantizado de estar disponible si __STDC_LIB_EXT1__ está definido por la implementación y si el usuario define __STDC_WANT_LIB_EXT1__ como la constante entera 1 antes de incluir <string.h>.Parámetros
| dest | - | puntero al arreglo de caracteres de destino |
| src | - | puntero al arreglo de caracteres de origen |
| count | - | número máximo de caracteres a copiar |
| destsz | - | el tamaño del búfer de destino |
Valor de retorno
destdest[0] (a menos que dest sea un puntero nulo o destsz sea cero o mayor que RSIZE_MAX) y puede sobrescribir el resto del arreglo de destino con valores no especificados.Notas
Según lo corregido por el DR 468 posterior a C11, strncpy_s, a diferencia de strcpy, solo puede sobrescribir el resto del arreglo de destino si ocurre un error.
A diferencia de strncpy, strncpy_s no rellena el arreglo de destino con ceros. Esta es una fuente común de errores al convertir código existente a la versión con verificación de límites.
Aunque el truncamiento para ajustarse al búfer de destino es un riesgo de seguridad y, por lo tanto, una violación de restricciones en tiempo de ejecución para strncpy_s, es posible obtener el comportamiento de truncamiento especificando count igual al tamaño del arreglo de destino menos uno: copiará los primeros count bytes y añadirá el terminador nulo como siempre: strncpy_s(dst, sizeof dst, src, (sizeof dst)-1);
Ejemplo
#define __STDC_WANT_LIB_EXT1__ 1
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char src[] = "hi";
char dest[6] = "abcdef"; // no null terminator
strncpy(dest, src, 5); // writes five characters 'h', 'i', '\0', '\0', '\0' to dest
printf("strncpy(dest, src, 5) to a 6-byte dest gives : ");
for (size_t n = 0; n < sizeof dest; ++n) {
char c = dest[n];
c ? printf("'%c' ", c) : printf("'\\0' ");
}
printf("\nstrncpy(dest2, src, 2) to a 2-byte dst gives : ");
char dest2[2];
strncpy(dest2, src, 2); // truncation: writes two characters 'h', 'i', to dest2
for (size_t n = 0; n < sizeof dest2; ++n) {
char c = dest2[n];
c ? printf("'%c' ", c) : printf("'\\0' ");
}
printf("\n");
#ifdef __STDC_LIB_EXT1__
set_constraint_handler_s(ignore_handler_s);
char dst1[6], src1[100] = "hello";
errno_t r1 = strncpy_s(dst1, 6, src1, 100); // writes 0 to r1, 6 characters to dst1
printf("dst1 = \"%s\", r1 = %d\n", dst1,r1); // 'h','e','l','l','o','\0' to dst1
char dst2[5], src2[7] = {'g','o','o','d','b','y','e'};
errno_t r2 = strncpy_s(dst2, 5, src2, 7); // copy overflows the destination array
printf("dst2 = \"%s\", r2 = %d\n", dst2,r2); // writes nonzero to r2,'\0' to dst2[0]
char dst3[5];
errno_t r3 = strncpy_s(dst3, 5, src2, 4); // writes 0 to r3, 5 characters to dst3
printf("dst3 = \"%s\", r3 = %d\n", dst3,r3); // 'g', 'o', 'o', 'd', '\0' to dst3
#endif
}
Posible salida:
strncpy(dest, src, 5) to a 6-byte dst gives : 'h' 'i' '\0' '\0' '\0' 'f'
strncpy(dest2, src, 2) to a 2-byte dst gives : 'h' 'i'
dst1 = "hello", r1 = 0
dst2 = "", r2 = 22
dst3 = "good", r3 = 0
Referencias
- Estándar C23 (ISO/IEC 9899:2024):
- 7.24.2.4 La función strncpy (p: TBD)
- K.3.7.1.4 La función strncpy_s (p: TBD)
- Estándar C17 (ISO/IEC 9899:2018):
- 7.24.2.4 La función strncpy (p: 265)
- K.3.7.1.4 La función strncpy_s (p: 447-448)
- Estándar C11 (ISO/IEC 9899:2011):
- 7.24.2.4 La función strncpy (p: 363-364)
- K.3.7.1.4 La función strncpy_s (p: 616-617)
- Estándar C99 (ISO/IEC 9899:1999):
- 7.21.2.4 La función strncpy (p: 326-327)
- Estándar C89/C90 (ISO/IEC 9899:1990):
- 4.11.2.4 La función strncpy
Véase también
(C11) |
copia una cadena a otra (función) |
(C11) |
copia un búfer a otro (función) |
(memoria dinámica TR) |
asigna una copia de una cadena hasta un tamaño especificado (función) |
Documentación de C++ para strncpy
| |