¿Cómo identifica C la matriz de final de caracteres cuando no hay un terminador nulo?

Dado que una matriz de caracteres C requiere un terminador nulo, el siguiente código imprime cuatro a sy algunos caracteres de basura.

char y[4] = {'a', 'a', 'a', 'a'}; printf("y = %s\n", y); 

Salida:

 y = aaaa  

Sin embargo, el siguiente código no produce caracteres de basura.

 char y[4] = {'a', 'a', 'a', 'a'}; char z[4] = {'b', 'b', 'b'}; printf("y = %s\n", y); printf("z = %s\n", z); 

Salida:

 y = aaaa z = bbb 

Entiendo que el cuarto carácter de z se inicializa automáticamente con un terminador nulo. También supongo que y y z se asignan uno junto al otro en la memoria.

Pero, ¿cómo C imprime correctamente solo 4 a en este caso y no en el primero? ¿Identifica que el siguiente byte ya está asignado a otra variable, por lo que debería dejar de imprimir más?

printf("y = %s\n", y); Es, en este caso, un comportamiento indefinido . En otras palabras, tuvo suerte: tal vez imprimió algunos caracteres invisibles antes de golpear un NUL, tal vez haya un cero después de la matriz debido a la alineación de la stack, tal vez las estrellas tengan razón.


No suelo dar detalles sobre “es UB, no tocar”, pero me siento extrañamente obligado a hacerlo.

Mira, aquí está tu progtwig:

 #include  int main() { char y[4] = {'a', 'a', 'a', 'a'}; char z[4] = {'b', 'b', 'b'}; printf("y = %s\n", y); printf("z = %s\n", z); } 

Y ahora voy a comstackrlo con mis banderas especiales de comstackción:

 $ cc -O3 so15727258.c -o so15727258 -fstack-protector-all -Wall 

Y ejecutarlo:

 $ ./so15727258 y = aaaa?>A??0F z = bbb 

Vaya, jaja, eso es basura total. Mejor aún, es basura aleatoria debido al protector de stack, por lo que no es ni siquiera (simplemente) determinista. Woot!


¿Todavía no está convencido? ¿Fueron las banderas especiales del comstackdor demasiado raras para ti? Tratar

 #include  int bar() { char x[4096]; } int foo() { char y[4] = {'a', 'a', 'a', 'a'}; char z[4] = {'b', 'b', 'b'}; printf("y = %s\n", y); printf("z = %s\n", z); } int main() { bar(); foo(); } 

Comstackrlo

 $ cc so15727258.c -o so15727258 -Wall 

Y ejecutarlo:

 $ ./so15727258 y = aaaa?????ic? z = bbb 

Todavía basura total! Solo recuerda, estos ejemplos son todos ilustrativos. Por supuesto, este es un comportamiento indefinido, por lo que podría obtener un resultado totalmente diferente y volver aquí y decirme “pero XYZ funciona”. Esa es la definición del comportamiento indefinido.

Su progtwig exhibe un comportamiento indefinido , incluso si parece funcionar. Las cadenas deben terminarse con '\0' para la mayoría de las operaciones de cadena y para imprimir.

Si se pregunta cómo es que todavía parece funcionar en algunos casos, puede haber cero bytes entre objetos (o en objetos adyacentes) y pueden servir como terminadores de cadena.

No tienes suerte … Puedes probarlo. Imprima el contenido de la memoria del byte justo después de la matriz. Puedo prometerte con mis ojos cerrados que es cero …