[C] char * vs char []

Iniciado por GGZ, 22 Marzo 2016, 01:26 AM

0 Miembros y 4 Visitantes están viendo este tema.

GGZ

¿Es lo mismo hacer esto?

#include <stdio.h>
#include <stdlib.h>

int main (void){

       char *s;
       s=(char *) malloc (3);

       s[0]='1';
       s[1]='2';
       s[2]='3';


       printf ("%s\n",s);

       return 0;
}


Que


#include <stdio.h>

int main (void){

       char s[3];

       char s[0]='1';
       char s[1]='2';
       char s[2]='3';

       printf ("%s\n",s);

}


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

Otra duda char *s="aloja"; char s[]="aloja";
¿Qué diferencias tienen?

Saludos!

LET'S DO STUFF!!

MAFUS

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.

GGZ

#2
Y si es de sólo lectura, ¿por qué este código sí funciona?

#include <stdio.h>

int main (void){

        char s[]="Aloja";
        char *z="Aloja";


        s[0]='H';
        s[1]='o';
        s[2]='l';
        s[3]='a';
        s[4]='0';

        z="POR QUE FUNCIONA";

        // s=&s[0]

        printf ("s:%s\n",s);
        printf ("z:%s\n",z);

        return 0;
}


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í?
LET'S DO STUFF!!

MAFUS

Sí, z cambia de dirección, es una cadena diferente. Lo puedes ver usando el argumento % p de printf.

fary

Cita de: 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.

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

saludos.
Un byte a la izquierda.

GGZ

Cita de: fary en 22 Marzo 2016, 07:03 AM
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
LET'S DO STUFF!!

HardForo

#6
Otra diferencia:


        s[0]='H';
        s[1]='o';
        s[2]='l';
        s[3]='a';
        s[4]='!';
        /*

Si intento seguir metiendo valores en un array, éste no modifica su tamaño asi que estoy escribiendo
en un lugar no reservado y puedo crear un "leak"

Podria haber aumentado el tamaño declarado del array por ejemplo a 10, reservando asi espacio limpio
para la escritura
*/
        //s[5]='!'; 



Duda:

CitarUna 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 ?
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

MAFUS

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

HardForo

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 ?
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

MAFUS

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.