Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Teoria de Punteros C

Estas en el tema de Teoria de Punteros C en el foro de C/C++ en Foros del Web. Buenas estoy empezando con este idioma después de mucha experiencia en POO y tenía ciertas dudas sobre los punteros y los char como por ejemplo: ...
  #1 (permalink)  
Antiguo 23/06/2014, 18:04
 
Fecha de Ingreso: noviembre-2012
Mensajes: 53
Antigüedad: 12 años, 1 mes
Puntos: 1
Pregunta Teoria de Punteros C

Buenas estoy empezando con este idioma después de mucha experiencia en POO
y tenía ciertas dudas sobre los punteros y los char como por ejemplo:

Código:
char cad1[]="hola";
en este caso cad1 es un vector de char con los valores 'h','o',l,'a','\0'

pero luego no puedes hacer esto
Código:
char cad1[4];
cad1="hola"
te dice que no le puedes asignar ese valor tipos incompatibles.
Pero te deja usar un método
Código:
strcpy( cad1, "hola");
por lo que yo creía "hola" representaba un vector de caracteres pero parece que no por que si no me dejaría darle este valor directamente

No obstante usando char* si te deja lo cual me extraña por que si "hola" no es un vector de caracteres entonces a que apuntaría la variable

Otra duda es con los Punteros a Punteros de char se supone que se puede crear un vector de char usando char **vector
pero no le encuentro la lógica osea vector apunta a un puntero que apunta a un vector de caracteres (ej "saludo1")pero como apuntas al siguiente vector de caracteres luego ej "saludo2"?

Intente recorrer un char ** pero no me funcionó
EJ
Código:
void mostrarChar(char **matriz)
{
    int f;
    for (f=0;f<7;f++)
    {
        printf("%s\n",matriz[f][0]);
    }
}

int main(int argc, char** argv)
{
    char **matriz={"Lunes","Martes","Miercoles","Jueves","Viernes","Sabado","Domingo"};
    mostrarChar(matriz);
    return (EXIT_SUCCESS);
}
Una ultima duda es que creo que no se puede usar scanf() con un puntero a char si no que tienes que hacerlo con un vector de char de tamaño fijo lo cual lo veo un desperdicio por que tu no sabes cuantas palabras puede escribir el usuario.

Bueno estos son los problemas mas complicados que estoy teniendo con C
quizá este muy acostumbrado a Java con su String etc XD

Me harías un gran favor si me pudieses aclarar un poco este cacao que tengo
Un saludo Y gracias de ante mano
  #2 (permalink)  
Antiguo 24/06/2014, 03:20
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 14 años, 6 meses
Puntos: 73
Respuesta: Teoria de Punteros C

En C, el nombre de un array es, en realidad, un puntero al primer elemento del array. Así, cuando declaras

char cad1[4];

cad1 es un puntero al primero de los cuatro elementos del array; por eso, cuando haces

cad1 = "Hola";

en realidad estás intentando asignar una cadena de caracteres a un puntero, que no es más que un tipo de variable que contiene una dirección de memoria.

En cambio, cuando haces

char *cad1 = "Hola";

lo que has heho es crear un puntero a char al que le has asignado la dirección de comienzo de la constante "Hola", que estará almacenada en alguna parte del mapa de memoria que se asigne al programa.

Dado que un puntero no es más que una variable que guarda una dirección de memoria, esta dirección puede corresponder perfectamente a la de otra variable que sea un puntero. Por tanto, cuando declaras

char **vector;

estás declarando un punero a puntero a char.

Una de las fortalezas/debilidades de C es que te permite utilizar los punteros como arrays; fortaleza porque te permite reservar la memoria que necesites según se necesite durante la ejecución del programa y acceder fácilmente a ella, y debilidad porque puede ser muy confuso si no tienes muy claro cómo funciona el asunto. Así, por ejemplo, puedes declarar

float *x;

más adelante, necesitas reservar memoria, por ejemplo, para 50 elementos:

x = (float *)malloc(50*sizeof(float));

y luego acceder a cada elemento, como si se tratase de un array:

z = x[7] / x[32];

Hay que tener cuidado porque C no establece control alguno sobre los límites de los arrays (o memoria reservada mediante punteros). Así, no te indicará error si intentas trabajar sobre el elemento x[60], pero puedes provocar un desastre al trabajar fuera de la memoria reservada para x (bien de manera fija, declarando float x[50], o bien de manera dinámica, mediante malloc() o alguna otra de las funciones de su familia). Además, puede que el problema no llegue a manifestarse en programas pequeños, o que provoque errores distintos en cada ejecución del programa.

Las inicializaciones en el momento de la declaración son complicadas. Te modifico ligeramente el ejemplo que posteaste (ejercicio de agudeza visual, busca las diferencias):

Código C:
Ver original
  1. void mostrarChar(char **matriz)
  2. {
  3.     int f;
  4.     for (f=0;f<7;f++)
  5.     {
  6.         printf("%s\n",matriz[f]);
  7.     }
  8. }
  9.  
  10. int main(int argc, char** argv)
  11. {
  12.     char *matriz[]={"Lunes","Martes","Miercoles","Jueves","Viernes","Sabado","Domingo"};
  13.     mostrarChar(matriz);
  14.     return (EXIT_SUCCESS);
  15. }

Si vas a trabajar con dobles punteros (o superior, que haberlos haylos) es mejor evitar la inicialización en el momento de la declaración y asignes los valores iniciales ya por programa. Al menos, hasta que le hayas cogido el punto.

Otra cosa que debes tener en cuuenta es que, en C, las cadenas de caracteres siempre terminan con el carácter ASCII 0 (NULL), y que éste también ocupa espacio. Así, por ejemplo, la cadena "Hola" necesita 5 caracteres, y no 4.

Bueno, espero haberte aclarado algo en lugar de liarte aún más. Saludos,
  #3 (permalink)  
Antiguo 24/06/2014, 04:37
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 16 años, 6 meses
Puntos: 61
Respuesta: Teoria de Punteros C

Los nombres de los arreglos son punteros constantes, por lo que no se pueden cambiar. Solo es posible inicializarlos.

Si intentas cambiar la direccion de memoria que guarda el compilador reclamará.
__________________
Visita mi perfil en LinkedIn
  #4 (permalink)  
Antiguo 25/06/2014, 00:28
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 14 años, 6 meses
Puntos: 73
Respuesta: Teoria de Punteros C

Cita:
Iniciado por CalgaryCorpus Ver Mensaje
Los nombres de los arreglos son punteros constantes, por lo que no se pueden cambiar. Solo es posible inicializarlos.

Si intentas cambiar la direccion de memoria que guarda el compilador reclamará.
Con algunos compiladores sí podría hacerse, de manera indirecta, mediante puntero a puntero. Pero no liemos más la cosa.
  #5 (permalink)  
Antiguo 25/06/2014, 05:25
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 16 años, 6 meses
Puntos: 61
Respuesta: Teoria de Punteros C

Cita:
Iniciado por Fw190 Ver Mensaje
Con algunos compiladores sí podría hacerse, de manera indirecta, mediante puntero a puntero. Pero no liemos más la cosa.
En mi opinión desinformada, no es posible modificar la dirección de memoria contenida en el identificador de un arreglo. No es que se lie la cosa, es que es imposible hacerlo. Asi que te reto a construir un programa que permite modificar la dirección de memoria contenida en el identificador de un arreglo. Solo por la educación mía y del resto.
__________________
Visita mi perfil en LinkedIn
  #6 (permalink)  
Antiguo 25/06/2014, 09:22
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 11 años, 2 meses
Puntos: 38
Respuesta: Teoria de Punteros C

Aquí nadie ha violado algo de lo que haya dicho el otro.
Que el nombre de un array es una contante y no se puede cambiar el valor si es correcto, pero que no se pueda utilizar mecanismos para saltar restricciones ¡Dios esto es C/C++! nada es imposible. XD

Código C++:
Ver original
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. int main (){
  5.    
  6.     char s[] = "wacalae!";
  7.    
  8.     char *p = NULL;
  9.    
  10.     p = &s[1];
  11.    
  12.     cout << p;
  13.    
  14.    
  15.     cin.ignore();
  16.     return 0;
  17. }

Y eso es lo que creo que se refiere Fw190. si creo un apuntador a cualquier parte de la cadena eso no es ninguna novedad XD
  #7 (permalink)  
Antiguo 25/06/2014, 09:30
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 16 años, 6 meses
Puntos: 61
Respuesta: Teoria de Punteros C

No lo creo.
El ejemplo mostrado es el uso normal de punteros.
Mientras que fw190 dice que puede modificar el contenido del identificador de un arreglo al usar un puntero a puntero.

Sostengo que en C++ eso es imposible.
Pero estoy dispuesto a aprender como se hace...

No estoy diciendo que los punteros a puntero no sirven o que no se pueden usar, sino que no se puede modificar el contenido del identificador de un arreglo
__________________
Visita mi perfil en LinkedIn
  #8 (permalink)  
Antiguo 25/06/2014, 10:01
Avatar de leosansan  
Fecha de Ingreso: mayo-2012
Ubicación: GRAN CANARIA
Mensajes: 194
Antigüedad: 12 años, 6 meses
Puntos: 49
Respuesta: Teoria de Punteros C

Cita:
Iniciado por vangodp Ver Mensaje
Y eso es lo que creo que se refiere Fw190. si creo un apuntador a cualquier parte de la cadena eso no es ninguna novedad XD
Pues esta vez estoy con CalgaryCorpus, no se puede modificar un array declarado.

Una cosa es :

Código C++:
Ver original
  1. #include <cstdlib>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5. int main(){
  6.   const char *ptr1 = "Hola", *ptr2 = "Hola2";
  7.   cout  << "ptr1:" << ptr1 << endl;
  8.   ptr1 = ptr2;
  9.   cout  << "ptr1:" << ptr1 << endl;
  10.   system("PAUSE");
  11.   return EXIT_SUCCESS;
  12. }

Que sí que se puede:

Cita:
ptr1:Hola
ptr1:Hola2
Presione una tecla para continuar . . .
Pero otra bien distinta es:

Código C++:
Ver original
  1. #include <cstdlib>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5. int main(){
  6.   const char ptr1[] = "Hola", *ptr2 = "Hola2";
  7.   cout << ptr1 << endl;
  8.   ptr1 = ptr2;
  9.   cout << ptr1 << endl;
  10.   system("PAUSE");
  11.   return EXIT_SUCCESS;
  12. }

Cita:
error: assignment of read-only variable 'ptr1'
¡¡¡Saluditos!!!

  #9 (permalink)  
Antiguo 25/06/2014, 10:23
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 11 años, 2 meses
Puntos: 38
Respuesta: Teoria de Punteros C

Cita:
Pues esta vez estoy con CalgaryCorpus, no se puede modificar un array declarado.
Bien veo que has entendido. ;)
Por que hasta ahora no he visto nadie en contra XD
Tu hablas de modificar y yo de saltar ciertas limitaciones con otros medios. A ver si lo pillan. ;)
El nombre de un array es un const si como ha dicho calgary no se puede modificar o al menos nunca vi de eso.
Pero punteros puedo crear a donde me plazca. ¿O me equivoco también? XD

Última edición por vangodp; 25/06/2014 a las 10:29
  #10 (permalink)  
Antiguo 25/06/2014, 10:55
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 16 años, 6 meses
Puntos: 61
Respuesta: Teoria de Punteros C

No todo puntero válidamente asignado es correcto desreferenciarlo. Hay alineamientos que respetar que produciran comportamiento inadecuado o el fin de la ejecucion de tu programa.
__________________
Visita mi perfil en LinkedIn
  #11 (permalink)  
Antiguo 27/06/2014, 06:17
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 14 años, 6 meses
Puntos: 73
Respuesta: Teoria de Punteros C

Cita:
Iniciado por CalgaryCorpus Ver Mensaje
En mi opinión desinformada, no es posible modificar la dirección de memoria contenida en el identificador de un arreglo. No es que se lie la cosa, es que es imposible hacerlo. Asi que te reto a construir un programa que permite modificar la dirección de memoria contenida en el identificador de un arreglo. Solo por la educación mía y del resto.
Si os fijáis bien, he dicho "con algunos compiladores sí podría hacerse", no he dicho que se pueda en general. La inmensa mayoría de los compiladores modernos (incluyendo los de uso más generalizado) no lo permitirán. La teoría es:

Código C:
Ver original
  1. int x[4] = {1,2,3,4};
  2. int **p;
  3.  
  4. p = (int **)&x;
  5. *p = (nueva_direccion_de_memoria);

Con esto, se supone que he cambiado la dirección a la que apuntaba x, por lo que, si ahora le digo que me imprima los valors del array x, me sacaría quién sabe qué. En la práctica, con los tres compiladores que tengo a mano en este momento (GCC, Tiny-C y LCC-Win32), x y &x tienen el mismo valor, p apuntaría al comienzo del array, y cualquier cambio que intente hacer a través del puntero p se traduce en que cambio el (los) valor(es) del (los) primer(os) elemento(s) del array, pero el array "sigue en su sitio". Entono, por tanto, un MEA CULPA parcial, aunque no descarto que algún compilador lo permita, por la misma razón que en este código:

Código C:
Ver original
  1. const int k=1;
  2. int *pk;
  3.  
  4. int main(void)
  5. {
  6.     pk = (int *)&k;
  7.     *pk = 7;
  8.     printf("%d\n", k);
  9.     return 0;
  10. }

con GCC y con LCC_Win32 el programa termina de forma catastrófica, mientras que con Tiny-C me imprime un valor de 7 (es decir, al final he modificado el valor de algo declarado como const entrando "por la puerta de atrás").

Concluyendo: Con punteros puedes hacer auténticas maravillas... o hundirte en la más honda de las miserias.
  #12 (permalink)  
Antiguo 27/06/2014, 13:37
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 16 años, 6 meses
Puntos: 61
Respuesta: Teoria de Punteros C

Cita:
Iniciado por Fw190 Ver Mensaje
... La inmensa mayoría de los compiladores modernos (incluyendo los de uso más generalizado) no lo permitirán.
Ningún compilador, moderno o no, lo permitirá (en mi opinión). No existe sintaxis para apoyar lo que dices que se puede hacer (modificar la dirección guardada en el identificador de un arreglo).

Es cierto que la especificación del lenguaje C ha dejado algunas definiciones abiertas y posibles de interpretar y con ello algunas instrucciones se comportarán de una manera en algunos compiladores y de otra manera en otros, y lo demuestras con el ejemplo. Es, para esos casos, un comportamiento indefinido y que hay que averiguar para cada compilador.

Pero eso no implica que algunos compiladores permitirán la modificación del contenido del identificador de un arreglo. Creo que es mala señal indicar que en alguno se podría. No es así.

Pero.. estoy dispuesto a aprender la manera sintáctica de hacerlo cuando funcione. Lo mostrado no lo logra.
__________________
Visita mi perfil en LinkedIn

Etiquetas: caracteres, char, punteros, vector
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 17:26.