print library c string char printf strcpy

library - ¿C tiene un tipo de cadena?



string copy c++ (7)

Recientemente comencé a programar en C, proveniente de Java y Python. Ahora, en mi libro he notado que para hacer un programa "Hello World", la sintaxis es algo como esto:

char message[10] strcpy(message, "Hello, world!") printf("%s/n", message);

Ahora, este ejemplo está usando una matriz char y me pregunté: ¿qué pasó con las cadenas? ¿Por qué no puedo simplemente usar uno de esos? Tal vez hay una manera diferente de hacer esto?


C no admite un tipo de cadena de primera clase.

C ++ tiene std :: string


C no tiene su propio tipo de datos de cadena como Java.

Solo podemos declarar el tipo de datos String en C usando una matriz de caracteres o un puntero de caracteres Por ejemplo:

char message[10]; or char *message;

Pero necesitas declarar al menos:

char message[14];

para copiar "¡Hola mundo!" en la variable del mensaje.

  • 13: longitud del "¡Hola mundo!"
  • 1: para ''/ 0'' carácter nulo que identifica el final de la cadena

C no tiene y nunca ha tenido un tipo de cadena nativa. Por convención, el lenguaje utiliza matrices de char terminadas con un carácter nulo, es decir, con ''/0'' . Las funciones y macros en las bibliotecas estándar del lenguaje brindan soporte para los arreglos de caracteres terminados en nulo, por ejemplo, strlen itera sobre un arreglo de caracteres hasta que encuentra un carácter ''/0'' y copias de strcpy desde la cadena de origen hasta que encuentra un ''/0'' .

El uso de cadenas terminadas en nulo en C refleja el hecho de que C estaba destinado a ser solo un poco más de alto nivel que el lenguaje ensamblador. Las cadenas terminadas en cero ya eran compatibles directamente en ese momento en lenguaje ensamblador para el PDP-10 y el PDP-11 .

Vale la pena señalar que esta propiedad de las cadenas en C conduce a bastantes errores de desbordamiento de búfer desagradables, que incluyen fallas de seguridad graves. Por ejemplo, si olvida terminar en nulo una cadena de caracteres pasada como el argumento fuente a strcpy , la función seguirá copiando bytes secuenciales de cualquier cosa que esté en la memoria después del final de la cadena fuente hasta que encuentre un 0 , potencialmente sobrescribir cualquier información valiosa que siga la ubicación de la cadena de destino en la memoria.

En su ejemplo de código, la cadena literal "¡Hola mundo!" se compilará en una matriz de caracteres de 14 bytes. Los primeros 13 bytes contendrán las letras, la coma, el espacio y el signo de exclamación y el byte final contendrá el carácter de terminador nulo ''/0'' , agregado automáticamente por el compilador. Si tuviera que acceder al último elemento de la matriz, lo encontraría igual a 0 . P.ej:

const char foo[] = "Hello, world!"; assert(foo[12] == ''!''); assert(foo[13] == ''/0'');

Sin embargo, en su ejemplo, el message solo tiene 10 bytes de longitud. strcpy escribirá los 14 bytes, incluido el terminador nulo, en la memoria comenzando en la dirección del message . Los primeros 10 bytes se escribirán en la memoria asignada en la pila para el message y los cuatro bytes restantes simplemente se escribirán en el extremo de la pila. La consecuencia de escribir esos cuatro bytes adicionales en la pila es difícil de predecir en este caso (en este ejemplo simple, puede que no duela nada), pero en el código del mundo real generalmente conduce a datos dañados o errores de violación de acceso a la memoria.


En C, una cadena simplemente es una matriz de caracteres, que termina con un byte nulo. Entonces, un char* menudo se pronuncia "cadena", cuando estás leyendo el código C.


No hay ningún tipo de string en C Tienes que usar matrices de char.

Por cierto, su código no funcionará, porque el tamaño de la matriz debería permitir que toda la matriz se ajuste más un carácter adicional de terminación en cero.


Para anotarlo en los idiomas que mencionaste:

Java:

String str = new String("Hello");

Pitón:

str = "Hello"

Tanto Java como Python tienen el concepto de una "cadena", C no tiene el concepto de una "cadena". C tiene matrices de caracteres que pueden venir en "solo lectura" o manipulables.

DO:

char * str = "Hello"; // the string "Hello/0" is pointed to by the character pointer // str. This "string" can not be modified (read only)

o

char str[] = "Hello"; // the characters: ''H''''e''''l''''l''''o''''/0'' have been copied to the // array str. You can change them via: str[x] = ''t''

Una matriz de caracteres es una secuencia de caracteres contiguos con un carácter centinela único al final (normalmente un terminador NULO ''/0'' ). Tenga en cuenta que el carácter centinela se anexa automáticamente de forma automática en los casos anteriores.


Primero, no necesitas hacer todo eso. En particular, el strcpy es redundante, no es necesario copiar una cadena solo para printf . Su message se puede definir con esa cadena en su lugar.

Segundo, no has dejado suficiente espacio para ese "¡Hola mundo!" cadena (el message debe tener al menos 14 caracteres, lo que permite el extra para el terminador nulo).

Sobre el porqué, sin embargo, es historia. En ensamblador, no hay cadenas, solo bytes, palabras, etc. Pascal tenía cadenas, pero hubo problemas con la escritura estática debido a eso: string[20] era un tipo diferente a esa string[40] . Hubo idiomas incluso en los primeros días que evitaron este problema, pero que causaron indirectas indirectas y indirectas de asignación, que eran mucho más un problema de eficiencia en aquel entonces.

C simplemente eligió evitar los gastos generales y mantener un nivel muy bajo. Las cadenas son matrices de caracteres. Las matrices están muy relacionadas con los indicadores que apuntan a su primer elemento. Cuando los tipos de matriz se "descomponen" a los tipos de puntero, la información del tamaño del búfer se pierde con el tipo estático, por lo que no se obtienen los antiguos problemas de cadena de Pascal.

En C ++, existe la clase std::string que evita muchos de estos problemas, y tiene los gastos generales de asignación dinámica, pero en estos días generalmente no nos importa eso. Y, en cualquier caso, std::string es una clase de biblioteca: hay una gestión de matrices de caracteres de estilo C debajo.