Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: GGZ en 22 Marzo 2016, 01:26 am



Título: [C] char * vs char []
Publicado por: GGZ en 22 Marzo 2016, 01:26 am
¿Es lo mismo hacer esto?

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main (void){
  5.  
  6.        char *s;
  7.        s=(char *) malloc (3);
  8.  
  9.        s[0]='1';
  10.        s[1]='2';
  11.        s[2]='3';
  12.  
  13.  
  14.        printf ("%s\n",s);
  15.  
  16.        return 0;
  17. }
  18.  

Que

Código
  1. #include <stdio.h>
  2.  
  3. int main (void){
  4.  
  5.        char s[3];
  6.  
  7.        char s[0]='1';
  8.        char s[1]='2';
  9.        char s[2]='3';
  10.  
  11.        printf ("%s\n",s);
  12.  
  13. }
  14.  

¿Podría hacer lo mismo utilizando char * pero sin utilizar malloc?

Otra duda
Código
  1. char *s="aloja"; char s[]="aloja";
¿Qué diferencias tienen?

Saludos!



Título: Re: [C] char * vs char []
Publicado por: MAFUS en 22 Marzo 2016, 02:13 am
Mucha:
El array contenido de un array, si es una variable automática, se guarda en la pila, en cambio en un puntero es este mismo el que se guarda en la pila y su contenido en el montón (heap) si se da su valor con malloc, calloc, realloc, etc. O en la zona de memoria de datos de sólo lectura si se le da el valor directamente con una cadena.
Si a un array se lo inicializa con una cadena, C crea código por debajo para copiar la cadena al array, en cambio el puntero guarda la cadena en memoria de solo lectura y apunta a ella.
A un array se le puede modificar el contenido, pero no sus características (zona a la que apunta su nombre,  el tamaño); al array se le puede cambiar la dirección a la que apunta, peri no su contenido si este es una cadena literal.
Con esto puedes ver que un array y un puntero,  aunque se vean muy parecidos, son dos cosas muy diferentes y debes elegir cual usar según el tratamiento que vayas a hacer de los datos.
Una cosa curiosa es que si dos arrays distintos los inicializas en el código con la misma cadena (sendas cadenas iguales), el compilador sólo guardará una cadena en memoria y los dos punteros apuntarán a ella. En cámbio,  si haces lo mismo pero con arrays cada uno de ellos guardará su propia copia de la cadena, así gastará el doble de espacio.


Título: Re: [C] char * vs char []
Publicado por: GGZ en 22 Marzo 2016, 02:23 am
Y si es de sólo lectura, ¿por qué este código sí funciona?
Código
  1. #include <stdio.h>
  2.  
  3. int main (void){
  4.  
  5.        char s[]="Aloja";
  6.        char *z="Aloja";
  7.  
  8.  
  9.        s[0]='H';
  10.        s[1]='o';
  11.        s[2]='l';
  12.        s[3]='a';
  13.        s[4]='0';
  14.  
  15.        z="POR QUE FUNCIONA";
  16.  
  17.        // s=&s[0]
  18.  
  19.        printf ("s:%s\n",s);
  20.        printf ("z:%s\n",z);
  21.  
  22.        return 0;
  23. }
  24.  

O sea a lo que te referís es que yo no puedo hacer esto: z[0]='X' no?

¿Eso funciona porque lo que hace el compilador es guardar una nueva cadena en la memoria y cambiar la direccion del puntero o algo así?


Título: Re: [C] char * vs char []
Publicado por: MAFUS en 22 Marzo 2016, 06:41 am
Sí, z cambia de dirección, es una cadena diferente. Lo puedes ver usando el argumento % p de printf.


Título: Re: [C] char * vs char []
Publicado por: fary en 22 Marzo 2016, 07:03 am
Sí, z cambia de dirección, es una cadena diferente. Lo puedes ver usando el argumento % p de printf.

Exácto, tambien lo puedes ver en un debugger.

saludos.


Título: Re: [C] char * vs char []
Publicado por: GGZ en 22 Marzo 2016, 17:42 pm
Exácto, tambien lo puedes ver en un debugger.

saludos.


Exacto*
Listo duda aclarada, no hace falta utilizar un debugger simplemente puedes hacer un printf con "%p" como decía MAFUS.

Gracias a los dos
Saludos! ;D


Título: Re: [C] char * vs char []
Publicado por: HardForo en 17 Abril 2016, 15:20 pm
Otra diferencia:

Código
  1.        s[0]='H';
  2.        s[1]='o';
  3.        s[2]='l';
  4.        s[3]='a';
  5.        s[4]='!';
  6.        /*
  7.  
  8. Si intento seguir metiendo valores en un array, éste no modifica su tamaño asi que estoy escribiendo
  9. en un lugar no reservado y puedo crear un "leak"
  10.  
  11. Podria haber aumentado el tamaño declarado del array por ejemplo a 10, reservando asi espacio limpio
  12. para la escritura
  13. */
  14.        //s[5]='!';  
  15.  


Duda:

Citar
Una cosa curiosa es que si dos arrays distintos los inicializas en el código con la misma cadena (sendas cadenas iguales), el compilador sólo guardará una cadena en memoria y los dos punteros apuntarán a ella. En cámbio,  si haces lo mismo pero con arrays cada uno de ellos guardará su propia copia de la cadena, así gastará el doble de espacio.

Hay un typo creo... en una de las dos sentencias no hablas de un array.... en cual ?


Título: Re: [C] char * vs char []
Publicado por: MAFUS en 17 Abril 2016, 15:59 pm
Tienes razón.
Donde dice: Una cosa curiosa es que si dos arrays distintos los inicializas en el código
Debe decir: Una cosa curiosa es que si dos punteros distintos los inicializas en el código


Título: Re: [C] char * vs char []
Publicado por: HardForo en 17 Abril 2016, 16:03 pm
Gracias @MAFUS, otra cosilla.......

El "Stack" como zona de memoria se utiliza por los compliques para asignar memoria en el "Heap" ? digo... eso lo hace el S.O. pero no le debe quedar fragmentada ni llena de agujeros y eso es tiempo de procesador (mientras que el stack no deja agujeros).

O hay otra razon ?


Título: Re: [C] char * vs char []
Publicado por: MAFUS en 17 Abril 2016, 16:21 pm
La pila tiene registros dedicados en la CPU e instrucciones en su repertorio para su manejo, lo que la hace rápida en su acceso. Pero debido a su naturaleza, está pensada para el manejo de las funciones, la pila se va moviendo arriba y abajo. Allí se guardan las variables locales de las funciones, llamadas automáticas. Cuándo una función termina y regresa el registro que marca el final de la pila regresa al punto en que estaba antes de llamar a dicha función, todo lo que había de ésta desaparece. Como puedes ver no se pueden guardar datos que trasciendan a la vida de las funciones, como las constantes.
Por otra parte grandes estructuras, arrays y clases, si se guardan en la pila, para moverlos entre funciones se gasta una gran cantidad de tiempo ya que hay que copiar su contenido una y otra vez, para eso se guardan en el montón (heap), así solo se copia un puntero, que al fin y al cabo es del tamaño igual a la palabra del procesador y por ende el objeto que más rápido se copia.


Título: Re: [C] char * vs char []
Publicado por: HardForo en 17 Abril 2016, 16:31 pm
Y el puntero como tal donde se guarda ?

Me imagino que si se declara localmente en la pila y sino en heap. Es asi ?


Título: Re: [C] char * vs char []
Publicado por: MAFUS en 17 Abril 2016, 17:04 pm
Un puntero es una variable más y sigue las mismas reglas que todas las variables.


Título: Re: [C] char * vs char []
Publicado por: HardForo en 17 Abril 2016, 17:47 pm
En StackOverflow tambien dicen eso.... "es una  tipo (de variable) mas"

"Pointers are just a type of variable, so they can be wherever you want them to be (on the heap if you malloc() them, on the stack if they're local variables, or in the data section if they're global) (http://stackoverflow.com/questions/3113668/location-of-pointers-and-global-variables-in-c)."

Sin embargo, no entiendo bien el tema de malloc() aqui: ¿ que tiene que ver si se reserva memoria para el contenido con donde queda el puntero en memoria ? (mas alla del caso particular de un puntero nulo)


Título: Re: [C] char * vs char []
Publicado por: ivancea96 en 17 Abril 2016, 18:40 pm
Sin embargo, no entiendo bien el tema de malloc() aqui: ¿ que tiene que ver si se reserva memoria para el contenido con donde queda el puntero en memoria ? (mas alla del caso particular de un puntero nulo)

De la misma forma que puedes reservar memoria dinámica para, por ejemplo, una estructura o un int, puedes reservar memoria dinámica para un puntero.

Código
  1. int** p = (int**)malloc(sizeof(int*));
  2. *p = (int*)malloc(sizeof(int));
  3. **p = 5;

En este caso habría 2 punteros: uno en el heap (*p), y el otro en la pila (p).


Título: Re: [C] char * vs char []
Publicado por: HardForo en 17 Abril 2016, 19:58 pm
Gracias Ivan, me imaginaba venia por punteros dobles el tema.... estoy probando y no me compila:

Código
  1. int main(void)
  2. {
  3. // En este caso habría 2 punteros: uno en el heap (*p), y el otro en la pila (p)
  4.  
  5. int** p = (int**)malloc(sizeof(int*));  
  6. *p = (int*)malloc(sizeof(int));  // en la pila
  7. **p = 5;
  8. }

12   19   C:\C++\heap_stack_ptrs.c   [Warning] incompatible implicit declaration of built-in function 'malloc'


Gracias desde ya....... lo miro y lo veo bien pero no quiere compilarse


Título: Re: [C] char * vs char []
Publicado por: ivancea96 en 17 Abril 2016, 20:07 pm
Pon #include <stdlib.h>, que es donde va malloc.


Título: Re: [C] char * vs char []
Publicado por: HardForo en 17 Abril 2016, 20:10 pm
Mil gracias Ivan