while sintaxis sentencia for errores ejemplos ciclos bucle c arrays pointers memory-address

sintaxis - Tengo tres bucles sobre una matriz de elementos(char*) en C. ¿Por qué falla el tercero?



sentencia break en c (3)

Cuando haces s = *(&s + 1) la variable s es una variable local en un ámbito implícito que solo contiene el bucle. Cuando lo hace, obtiene la dirección de esa variable local, que no está relacionada con ninguna de las matrices.

La diferencia con el ciclo anterior es que hay un puntero al primer elemento de la matriz.

Para explicarlo un poco más "gráficamente", lo que tienes en el último ciclo es algo así como

+----+ +---+ +------------+ | &s | ---> | s | ---> | family2[0] | +----+ +---+ +------------+

Es decir, &s apunta a s , y s apunta a family2[0] .

Cuando lo haces &s + 1 efectivamente tienes algo como

+------------+ | family2[0] | +------------+ ^ | +---+---- | s | ... +---+---- ^ ^ | | &s &s + 1

Al experimentar con métodos para recorrer una serie de cadenas en C, desarrollé el siguiente pequeño programa:

#include <stdio.h> #include <stdlib.h> #include <string.h> typedef char* string; int main() { char *family1[4] = {"father", "mother", "son", NULL}; string family2[4] = {"father", "mother", "son", NULL}; /* Loop #1: Using a simple pointer to step through "family1". */ for (char **p = family1; *p != NULL; p++) { printf("%s/n", *p); } putchar(''/n''); /* Loop #2: Using the typedef for clarity and stepping through * family2. */ for (string *s = family2; *s != NULL; s++) { printf("%s/n", *s); } putchar(''/n''); /* Loop #3: Again, we use the pointer, but with a unique increment * step in our for loop. This fails to work. Why? */ for (string s = family2[0]; s != NULL; s = *(&s + 1)) { printf("%s/n", s); } }

Mi pregunta específica involucra el fracaso de Loop # 3. Cuando se ejecuta a través del depurador, los bucles n. ° 1 y n. ° 2 se completan con éxito, pero el último bucle falla por un motivo desconocido. No hubiera preguntado esto aquí, excepto por el hecho de que me muestra que tengo un malentendido crítico con respecto al operador "&".

Mi pregunta (y la comprensión actual) es esta:

family2 es una matriz de puntero a char. Por lo tanto, cuando s se establece en family2[0] tenemos un (char*) apunta a "padre". Por lo tanto, tomar &s debería darnos el equivalente de family2 , apuntando al primer elemento de family2 después del decaimiento esperado del puntero. ¿Por qué, entonces, *(&s + 1) apunta al siguiente elemento, como se esperaba?

Muchas gracias,
crisis de vida

EDITAR - Actualización y Lecciones Aprendidas:

La siguiente lista es un resumen de todos los hechos e interpretaciones relevantes que explican por qué el tercer ciclo no funciona como los dos primeros.

  1. s es una variable separada que contiene una copia del valor (un puntero a char) de la family2[0] variables2 family2[0] . Es decir, estos dos valores equivalentes se colocan en ubicaciones SEPARADAS en la memoria.
  2. family2[0] hasta family2[3] son elementos contiguos de la memoria, y s no tiene presencia en este espacio, aunque sí contiene el mismo valor que está almacenado en family2[0] al inicio de nuestro ciclo.
  3. Estos dos primeros hechos significan que &s y &family2[0] NO son iguales. Por lo tanto, agregar uno a &s devolverá un puntero a datos desconocidos / indefinidos, mientras que agregar uno a &family2[0] le dará &family2[1] , según lo desee.
  4. Además, el paso de actualización en el tercer bucle for no da como resultado un avance en la memoria en cada iteración. Esto es porque &s es constante a lo largo de todas las iteraciones de nuestro ciclo. Esta es la causa del ciclo infinito observado.

¡Gracias a todos por su ayuda!
crisis de vida


#include <stdio.h> #include <stdlib.h> #include <string.h> typedef char* string; int main() { char *family1[4] = { "father", "mother", "son", NULL }; string family2[4] = { "father", "mother", "son", NULL }; /* Loop #1: Using a simple pointer to step through "family1". */ for (char **p = family1; *p != NULL; p++) { printf("%s/n", *p); } putchar(''/n''); /* Loop #2: Using the typedef for clarity and stepping through * family2. */ for (string *s = family2; *s != NULL; s++) { printf("%s/n", *s); } putchar(''/n''); /* Loop #3: Again, we use the pointer, but with a unique increment * step in our for loop. This fails to work. Why? */ /*for (string s = family2[0]; s != NULL; s = *(&s + 1)) { printf("%s/n", s); } */ for (int j = 0; j < 3; j++) { printf("%d ",family2[j]); printf("%d/n", strlen(family2[j])); } printf("/n"); int i = 0; for (string s = family2[i]; i != 3; s = (s + strlen(family2[i]) + 2),i++) { printf("%d ",s); printf("%s/n", s); } system("pause");

}

este es un ejemplo revisado de su código, si lo ejecuta, encontrará el cambio de la dirección del punto y de la familia2, entonces comprenderá la relación del bucle n. ° 3.


Las imágenes ayudan mucho:

+----------+ | "father" | +----------+ +----------+ +-------+ NULL /-----------→1000 | "mother" | | "son" | ↑ +-----+ ↑ +----------+ +-------+ | | s | ? | 2000 2500 | +-----+ | ↑ ↑ | 6000 6008 +----------------+----------------+--------------+--------------+ | family2[0] | family2[1] | family2[2] | family2[3] | +----------------+----------------+--------------+--------------+ 5000 5008 5016 5024 ( &s refers to 6000 ) ( &s+1 refers to 6008 but ) ( *(&s+1) invokes UB )

Direcciones elegidas como enteros aleatorios para simplicidad

Lo que family2[0] aquí es que, aunque tanto s como family2[0] apuntan a la misma dirección base del literal de cadena "father" , los punteros no están relacionados entre sí y tienen su propia ubicación de memoria diferente donde se almacenan. *(&s+1) != family2[1] .

Tocas UB cuando lo haces *(&s + 1) porque &s + 1 es una ubicación de memoria que no debes manipular, es decir, no pertenece a ningún objeto que hayas creado. Nunca se sabe lo que está almacenado en there => Comportamiento indefinido.

¡Gracias @ 2501 por señalar varios errores!