2010-04-28 10 views
12

En mi clase estamos escribiendo nuestra propia copia de la función malloc() de C. Para probar mi código (que en la actualidad puede asignar bien el espacio) que estaba usando:¿Cuándo deja de imprimirse printf ("% s", char *)?

char* ptr = my_malloc(6*sizeof(char)); 
memcpy(ptr, "Hello\n", 6*sizeof(char)); 
printf("%s", ptr); 

La salida típica sería la siguiente:

Hello 
Unprintable character 

Algunos depuración pensó que mi código no estaba causando este per se , como la memoria de PTR es de la siguiente manera:

[24 bytes de información de metadatos] [Número de bytes solicitados] [Relleno]

por lo que pensé que estaba alcanzando printf en el relleno, que es solo basura. Así que me encontré con una prueba de: printf("%s", "test\nd"); y tengo:

test 
d 

que me pregunto, ¿cuándo printf ("% s", char *) detener la impresión de caracteres?

Respuesta

26

Se detiene la impresión cuando alcanza un carácter nulo (\0), porque %s espera que la cadena sea nula terminada (es decir, espera que el argumento sea una cadena C).

La cadena literal "test\nd" tiene una terminación nula (todos los literales de cadena terminan nulos). Sin embargo, su matriz de caracteres ptr no se debe a que solo copia seis caracteres en el búfer (Hello\n) y no copia el séptimo carácter, el terminador nulo.

3

Las cadenas C terminan nulamente (hay un carácter \ 0 al final), así es como C sabe cuándo detener la impresión o tratar el búfer como una cadena. Es su responsabilidad nunca colocar una cadena en un espacio más largo que el que ha asignado.

Tenga en cuenta que Hello \ n no es una cadena de seis caracteres, en realidad es una cadena de siete caracteres. Utiliza cinco para Hola, uno para la línea nueva y uno para el terminador nulo.

Tratar de encajar 7 caracteres en un búfer de seis caracteres se considera un error, no estoy seguro de si es responsable de los problemas que tiene actualmente, pero parece que la copia de 6 caracteres no copiaría el terminador nulo . Así que, en realidad, espero que su impresión vaya más allá del Hello y se convierta en basura real.

+0

Dur, que debería usar \ 0 a interrumpir las cadenas? Dur Dur Dur – user327406

+0

No tiene que agregar \ 0 usted mismo. Cuando crea una cadena literal u obtiene una como entrada, C la agrega por usted. En realidad, no ves el \ 0. Esa cadena "Hello \ n" tiene siete caracteres si mira el código de ensamblaje real. – Uri

0

cuando llega a cero. necesitas 7 caracteres.

5

James tiene razón acerca de la detención de printf cuando llega al carácter nulo, y Uri está en lo cierto al tener que asignar un búfer de 7 caracteres para mantener "hello \ n".

Parte de la confusión con los terminadores se mitigaría si usara el idioma C habitual para copiar una cadena: strcpy(ptr, "Hello\n"), en lugar de memcpy.

también, por definición, sizeof (char) == 1 en C, por lo que es redundante 6*sizeof(char)

+2

6 * sizeof (char) puede ser redundante pero, en mi opinión, es una buena práctica por las razones simples (1) si un char en alguna arquitectura nueva no es = 1 o (2) este código se transporta a wchar_t .. .. – Eric

+4

No sería solo una nueva arquitectura, sería un lenguaje nuevo. Si 'sizeof (char)! = 1', ya no está programando en C. http://stackoverflow.com/questions/2215445/are-there-machines-where-sizeofchar-1 –

Cuestiones relacionadas