Tengo una matriz de punteros a matrices, en una función. Necesito acceder a esa matriz en otra función.

Matriz de punteros

char *ptr[size + 1];

Hice un puntero global

char *p;

Que apunté a ptr (en la misma función que ptr)

p = *ptr;

Luego intenté acceder a ptr desde la otra función

void otherFunction(void){
    for(int n = 0; n < 6; n++)
    {
        char* str = &p[n];
        printf("%i %s\n", n, str);
    }
}

Cuando

ptr[0] = "abcd"
ptr[1] = "bcde"
ptr[2] = "cdef"
ptr[3] = "defg"
ptr[4] = "efgh"
ptr[5] = "fghi"

La salida de otherfunction(); es:

0 abcd
1 bcd
2 cd
3 d
4 
5 

Quiero que la salida sea

 0 abcd
 1 bcde
 2 cdef
 3 defg
 4 efgh
 5 fghi

Mis preguntas son: (0) qué va mal aquí. (1) ¿Cómo lo soluciono? (2) ¿O hay una mejor manera de hacerlo? los requisitos son otherfunction() no puede aceptar ningún argumento y ptr debe permanecer local a su función. (Estoy seguro de que el otro código no contribuye al problema y no hay ningún problema con ptr)

0
user7045711 2 ene. 2017 a las 06:55
1
p = *ptr; elimina las referencias ptr y es idéntico a decir p = ptr[0];
 – 
Goodies
2 ene. 2017 a las 06:58
1
Sabes que puedes pasar parámetros, ¿no?
 – 
Iharob Al Asimi
2 ene. 2017 a las 06:59
4
Cabe señalar que los punteros globales rara vez son una buena idea, especialmente si los va a apuntar a variables locales. Una vez que se complete la función, la pila se limpiará y obtendrá un comportamiento indefinido.
 – 
Goodies
2 ene. 2017 a las 07:00
2
Y ese es solo un escenario simple en el que esto sería una mala idea, los indicadores globales son malos casi para cualquier situación. Además, siempre hay una solución diferente a usar variables globales y siempre son mejores soluciones que usar variables globales, por lo que recomiendo evitar las variables globales tanto como sea posible, incluso si suena demasiado drástico. Por supuesto, este comentario es principalmente para el OP.
 – 
Iharob Al Asimi
2 ene. 2017 a las 07:02
1
p = ptr; sería un error
 – 
M.M
2 ene. 2017 a las 07:08

3 respuestas

ptr es una matriz de puntero.

char **p = ptr;

char *str = p[n];
printf("%i %s\n", n, str);
3
Stargateur 2 ene. 2017 a las 06:59
¿Cuál es el uso de p? ¿Por qué no simplemente hacer char* str = ptr[n];?
 – 
Lundin
2 ene. 2017 a las 14:59
No sé, pregúntale al OP. Quizás p sea global pero no ptr. Esta respuesta es solo una respuesta rápida no exhaustiva, ya he votado a favor de las otras dos por eso.
 – 
Stargateur
2 ene. 2017 a las 15:39
Sin embargo, ese es el punto. Lo más probable es que el OP no debería tener su "puntero global" para empezar.
 – 
Lundin
2 ene. 2017 a las 15:48

char *ptr[size + 1];

char* p = *ptr;

char* str = &p[n];

Esto hace que p apunte a la primera cadena de la matriz de cadenas ptr, y luego str iterará sobre esa cadena carácter por carácter. Creo que lo que pretendías hacer es esto:

char** p = ptr; // p points to the first string of ptr
...
char* str = p[n]; // str points to the nth string of ptr

Aparte de eso, usar punteros globales no es una buena idea. Posiblemente sea mejor pasar ptr a la función otherFunction, que tendría el prototipo:

void otherFunction(char** p);

Y lo llamas con ptr:

otherFunction(ptr);
2
A.S.H 2 ene. 2017 a las 07:06

(0) ¿Qué va mal aquí? (1) ¿Cómo lo soluciono? (2) ¿O hay una mejor manera de hacerlo?

(0) Todo el diseño del programa. El uso de variables globales como esta, punteros en particular, es una forma de programación espagueti y debe evitarse. Está creando acoplamientos estrechos y dependencias entre todo tipo de partes no relacionadas en su programa.

En general, la presencia de punteros a punteros suele ser una indicación de un diseño deficiente. Los punteros a punteros tienen algunos usos válidos, para casos especiales como devolver un puntero modificado a través de un parámetro de función. No hay ninguna razón aparente para utilizarlos en su caso.

(1) Mediante el uso de un par de calificadores de tipo y especificadores de almacenamiento para reducir el alcance de esas variables globales desordenadas. En su lugar, acceda a la matriz de punteros a través de las funciones setter / getter.

(2) Sí, cambie el programa a algo como el siguiente código:

static const char* ptr [] =
{
  "abcd",
  "bcde",
  "cdef",
  "defg",
  "efgh",
  "fghi",
  NULL
};

inline const char* get_str (size_t index)
{
  return ptr[index];
}

inline void set_str (size_t index, const char* str)
{
  ptr[index] = str;
}
1
Lundin 2 ene. 2017 a las 13:54
"En general, la presencia de punteros a punteros suele ser una indicación de un diseño deficiente", entonces, int main(int, char **); ¿es un diseño deficiente? Esto es realmente estricto. Estoy totalmente de acuerdo con toda tu respuesta excepto esa. Los programadores de 3 estrellas deben ser castigados, estoy de acuerdo pero, ¿dos inicios? Hay muchos casos en los que son válidos.
 – 
Stargateur
2 ene. 2017 a las 14:06
char** argv estrictamente hablando no es una forma válida de main, pero por supuesto char* argv[] se descompone en un puntero a puntero, por lo que son equivalentes. La presencia de dos estrellas significa que está haciendo algo fuera de lo común, como devolver un puntero a datos malloc: ed a través de un parámetro, lo cual está perfectamente bien. El uso de puntero a puntero en otras situaciones es, en mi experiencia, con mayor frecuencia el resultado de la confusión del programador. Por ejemplo, el uso incorrecto de char** ptr = malloc(n*sizeof(*ptr)), para asignar una "matriz 2D".
 – 
Lundin
2 ene. 2017 a las 14:56
Sin embargo, estaría bien usar un puntero a puntero al asignar una matriz de punteros dinámicamente, aunque sería más correcto usar un puntero de matriz en ese caso. Los punteros a punteros están perfectamente bien si realmente sabe lo que está haciendo.
 – 
Lundin
2 ene. 2017 a las 14:57