Articulo de referencia

Cadena terminada en nulo

En programación informática , una cadena terminada en nulo es una cadena de caracteres almacenada como una matriz que contiene los caracteres y termina con un carácter nulo (un ...

En programación informática , una cadena terminada en nulo es una cadena de caracteres almacenada como una matriz que contiene los caracteres y termina con un carácter nulo (un carácter con un valor interno de cero, llamado "NUL" en este artículo, que no es lo mismo que el glifo cero). Los nombres alternativos son cadena C , que se refiere al lenguaje de programación C , y ASCIIZ [ 1 ] (aunque C puede usar codificaciones distintas de ASCII ).

La longitud de una cadena se determina buscando el primer carácter nulo (NUL). Esto puede ser lento, ya que requiere una complejidad temporal de O( n ) ( tiempo lineal ) con respecto a la longitud de la cadena. Además, implica que una cadena no puede contener un carácter nulo (si bien existe un carácter nulo en memoria, se encuentra después del último carácter, no dentro de la cadena).

Historia

Las cadenas terminadas en nulo se generaban mediante la .ASCIZdirectiva de los lenguajes ensambladores del PDP-11 y la directiva del lenguaje ensamblador de macros MACRO-10 para el PDP-10 . Estas son anteriores al desarrollo del lenguaje de programación C, pero a menudo se utilizaban otros tipos de cadenas.ASCIZ

En la época en que se desarrolló C (y los lenguajes de los que se derivó), la memoria era extremadamente limitada, por lo que usar solo un byte de sobrecarga para almacenar la longitud de una cadena resultaba atractivo. La única alternativa popular en ese momento, generalmente llamada "cadena Pascal" (un término más moderno es " con prefijo de longitud "), usaba un byte inicial para almacenar la longitud de la cadena. Esto permitía que la cadena contuviera NUL y hacía que encontrar la longitud requiriera solo un acceso a memoria ( tiempo constante O(1) ), pero limitaba la longitud de la cadena a 255 caracteres. El diseñador de C, Dennis Ritchie, optó por seguir la convención de terminación nula para evitar la limitación en la longitud de una cadena y porque mantener el conteo parecía, en su experiencia, menos conveniente que usar un terminador. [ 2 ]

Esto influyó en el diseño del conjunto de instrucciones de la CPU . Algunas CPU de las décadas de 1970 y 1980, como la Zilog Z80 y la DEC VAX , tenían instrucciones específicas para manejar cadenas con prefijo de longitud. Sin embargo, a medida que la cadena terminada en nulo ganaba popularidad, los diseñadores de CPU comenzaron a tenerla en cuenta, como se observa, por ejemplo, en la decisión de IBM de añadir las instrucciones "Logical String Assist" al ES/9000 520 en 1992 y las instrucciones de cadena vectorial al IBM z13 en 2015. [ 3 ]

El desarrollador de FreeBSD, Poul-Henning Kamp , escribió en ACM Queue que la victoria de las cadenas terminadas en nulo sobre una longitud de 2 bytes (no de un byte) fue "el error de un byte más costoso" de la historia. [ 4 ]

Limitaciones

Si bien esta representación es sencilla de implementar, ha sido propensa a errores y problemas de rendimiento.

Históricamente, la terminación nula ha creado problemas de seguridad . [ 5 ] Un carácter nulo insertado en medio de una cadena la truncará inesperadamente. [ 6 ] Un error común era no asignar el espacio adicional para el carácter nulo, por lo que se escribía sobre la memoria adyacente. Otro era no escribir el carácter nulo en absoluto, lo que a menudo no se detectaba durante las pruebas porque el bloque de memoria ya contenía ceros. Debido al costo de encontrar la longitud, muchos programas no se molestaban en hacerlo antes de copiar una cadena a un búfer de tamaño fijo , lo que provocaba un desbordamiento del búfer si era demasiado larga.

La imposibilidad de almacenar un cero exige que los datos de texto y binarios se mantengan separados y se procesen con funciones diferentes (en este último caso, también se requiere especificar la longitud de los datos). Esto puede generar redundancia de código y errores al utilizar la función incorrecta.

Los problemas de velocidad al encontrar la longitud generalmente se pueden mitigar combinándolo con otra operación que sea O( n ), como en strlcpy. Sin embargo, esto no siempre resulta en una API intuitiva .

Codificaciones de caracteres

Las cadenas terminadas en nulo requieren que la codificación no utilice un byte cero (0x00) en ningún lugar; por lo tanto, no es posible almacenar todas las cadenas ASCII o UTF-8 posibles . [ 7 ] [ 8 ] [ 9 ] Sin embargo, es común almacenar el subconjunto de ASCII o UTF-8 (todos los caracteres excepto NUL) en cadenas terminadas en nulo. Algunos sistemas utilizan " UTF-8 modificado " que codifica NUL como dos bytes distintos de cero (0xC0, 0x80) y, por lo tanto, permite almacenar todas las cadenas posibles. Esto no está permitido por el estándar UTF-8, porque es una codificación demasiado larga y se considera un riesgo de seguridad. En su lugar, se puede utilizar algún otro byte como final de cadena, como 0xFE o 0xFF, que no se utilizan en UTF-8.

UTF-16 utiliza enteros de 2 bytes y, dado que cualquiera de los bytes puede ser cero (y de hecho , todos los demás bytes lo son al representar texto ASCII), no se puede almacenar en una cadena de bytes terminada en nulo. Sin embargo, algunos lenguajes implementan una cadena de caracteres UTF-16 de 16 bits , terminada por un carácter nulo de 16 bits (0x0000).

mejoras

Se han realizado numerosos intentos para reducir la probabilidad de errores en el manejo de cadenas en C. Una estrategia consiste en añadir funciones más seguras, como `<string>` strdupy ` <string> strlcpy`, y desaconsejar el uso de funciones inseguras, como ` gets<string>`. Otra estrategia consiste en añadir una capa de abstracción orientada a objetos a las cadenas de C para que solo se puedan realizar llamadas seguras. Sin embargo, aún es posible llamar a las funciones inseguras.

La mayoría de las bibliotecas modernas reemplazan las cadenas C con una estructura que contiene un valor de longitud de 32 bits o más (mucho más de lo que se consideraba para las cadenas con prefijo de longitud), y a menudo agregan otro puntero, un contador de referencias e incluso un NUL para acelerar la conversión de vuelta a una cadena C. La memoria es mucho mayor ahora, de modo que si la adición de 3 (o 16, o más) bytes a cada cadena es un problema real el software tendrá que lidiar con tantas cadenas pequeñas que algún otro método de almacenamiento ahorrará aún más memoria (por ejemplo, puede haber tantos duplicados que una tabla hash usará menos memoria). Los ejemplos incluyen la Biblioteca de Plantillas Estándar de C++ , Qt , MFC y la implementación basada en C de Core Foundation, así como su hermano Objective-C de Foundation , ambos de Apple. También se pueden usar estructuras más complejas para almacenar cadenas como la cuerda .std::stringQStringCStringCFStringNSString

Véase también

Referencias

  1. "Capítulo 15 - Lenguaje ensamblador MIPS" (PDF) . Universidad de Carleton . Consultado el 9 de octubre de 2023 .
  2. Ritchie, Dennis M. (1996). «El desarrollo del lenguaje C». En Bergin, Jr., Thomas J.; Gibson, Jr., Richard G. (eds.). Historia de los lenguajes de programación (2.ª ed.). Nueva York: ACM Press. ISBN  0-201-89502-1 vía Addison-Wesley (Reading, Massachusetts).
  3. Principios de funcionamiento de la arquitectura IBM z/
  4. Kamp, Poul-Henning (25 de julio de 2011), "El error de un byte más costoso", ACM Queue , 9 (7): 40– 43, doi : 10.1145/2001562.2010365 , ISSN 1542-7730 , S2CID 30282393  
  5. Rain Forest Puppy (9 de septiembre de 1999). "Problemas de CGI en Perl" . Phrack Magazine . 9 (55). artofhacking.com: 7. Recuperado el 3 de enero de 2016 .
  6. "¿Inyección de byte nulo en PHP?" .
  7. Yergeau, François (noviembre de 2003). "UTF-8, un formato de transformación de ISO 10646" . Recuperado el 19 de septiembre de 2013 .
  8. "Tabla de caracteres Unicode/UTF-8" . Consultado el 13 de septiembre de 2013 .
  9. Kuhn, Markus. "UTF-8 y preguntas frecuentes sobre Unicode" . Consultado el 13 de septiembre de 2013 .
Obtenido de " https://en.wikipedia.org/w/index.php?title=Null-terminated_string&oldid=1282212915 "