¿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!
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.
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í?
Sí, z cambia de dirección, es una cadena diferente. Lo puedes ver usando el argumento % p de printf.
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.
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
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 ?
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
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 ?
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.
Y el puntero como tal donde se guarda ?
Me imagino que si se declara localmente en la pila y sino en heap. Es asi ?
Un puntero es una variable más y sigue las mismas reglas que todas las variables.
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)
Cita de: boctulus en 17 Abril 2016, 17:47 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.
int** p = (int**)malloc(sizeof(int*));
*p = (int*)malloc(sizeof(int));
**p = 5;
En este caso habría 2 punteros: uno en el
heap (*p), y el otro en la pila (p).
Gracias Ivan, me imaginaba venia por punteros dobles el tema.... estoy probando y no me compila:
int main(void)
{
// En este caso habría 2 punteros: uno en el heap (*p), y el otro en la pila (p)
int** p = (int**)malloc(sizeof(int*));
*p = (int*)malloc(sizeof(int)); // en la pila
**p = 5;
}
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
Pon #include <stdlib.h>, que es donde va malloc.
Mil gracias Ivan