Actualmente estoy aprendiendo C y escribí este programa para verificar si el carácter '\ 0' está realmente al final de las cadenas, como se indica en "K y R".
Sin embargo, tuve el resultado más extraño.
Si comento el "int lista[] = {0, 1, 2, 3, 4};" declaración fuera del programa (esta es una declaración que no tiene nada que ver con las otras declaraciones de este programa, era parte de otra prueba que iba a hacer). la salida del programa sale como se esperaba, detectando un carácter '\ 0' que finaliza la cadena. Sin embargo, si dejo la declaración sin comentar, la salida del programa detecta dos caracteres '\0' al final de la cadena. ¿Por qué sucede esto?
Este es el programa con la sentencia sin comentar:
#include <stdio.h> int main(void) { int lista[] = {0, 1, 2, 3, 4}; char string[] = "linhas"; for (int i = 0; i <= sizeof(string); i++) { if (string[i] != '\0') { printf("%c\n", string[i]); } else { printf("this dawmn null char\n"); } } }Esto da como resultado:
l i n h a s this dawmn null char this dawmn null chareste es el programa con la línea comentada:
#include <stdio.h> int main(void) { /*int lista[] = {0, 1, 2, 3, 4};*/ char string[] = "linhas"; for (int i = 0; i <= sizeof(string); i++) { if (string[i] != '\0') { printf("%c\n", string[i]); } else { printf("this dawmn null char\n"); } } }da salida:
l i n h a s this dawmn null chartu bucle
for (int i = 0; i <= sizeof(string); i++)está siempre tan ligeramente mal. Debería ser
for (int i = 0; i < sizeof(string); i++) Al usar <= , realiza demasiados viajes a través del bucle y accede a la memoria fuera de la matriz de string . Parece que, con la matriz de lista en su lugar, el byte adicional al que accede por error (fuera de la matriz de string ) resulta ser un 0, por lo que obtiene una segunda impresión adicional de su mensaje "this dawmn null char".
Pero luego, cuando comenta la matriz lista , debe ser el caso de que el byte adicional al que accede por error no sea 0, por lo que se imprime como sí mismo, en su lugar. Puede ser un carácter de control invisible, por lo que no ve nada. Sugiero cambiar su código a
if (string[i] != '\0') printf("string contains %d\n", string[i]); else printf("this damn null char\n");para ver esto más claro.
La lección importante aquí es que si tiene un bucle que se supone que debe ejecutarse N veces, hay dos formas de escribirlo. En C, la gran mayoría de las veces, desea escribirlo como
for(i = 0; i < N; i++)Ese es un bucle "basado en 0", que va de 0 a N-1, para un total de N viajes. De vez en cuando, desea un bucle basado en 1:
for(i = 1; i <= N; i++)Esto va de 1 a N, nuevamente para un total de N viajes. pero si escribes
for(i = 0; i <= N; i++) /* usually WRONG */su bucle va de 0 a N, para un total de N+1 viajes.
¡No confunda strlen(string) que en su caso debería ser 6 y sizeof(string) que es el tamaño de la matriz, incluido el byte '\0' ! ;-)
En el caso de una cadena declarada como una matriz con "tamaño automático", la diferencia es solo una, pero si tuviera char string[256] , sizeof(string) no sería lo mismo que strlen(string) + 1 .
Con char *string , sizeof(string) probablemente sería 8 o 4 .
@SteveSummit ha explicado todo en detalle. Aquí hay una respuesta corta.
Acceder al elemento lista[sizeof(lista)] es un comportamiento indefinido, por lo que no tiene sentido discutir qué valor debería tener. Cité sin sentido, porque puede ser bueno comprender cómo se manifiesta el comportamiento indefinido con fines de depuración. Pero si este código entrara en producción, NUNCA debe acceder a lista[sizeof(lista)] . Siempre está fuera de límites y siempre es un error.