Autor Tema: Arreglos en C

0 Usuarios y 2 Visitantes están viendo este tema.

18 Febrero, 2014, 10:59 pm
Leído 3873 veces

lul

  • $$\Large \color{#5e8d56}\pi\,\pi\,\pi$$
  • Mensajes: 126
  • Karma: +0/-0
  • Sexo: Femenino
¿Cada vez que creo un arreglo hay que hacer un malloc? ¿O cuándo habria que usar malloc con arreglos?

Gracias.

18 Febrero, 2014, 11:10 pm
Respuesta #1

pierrot

  • pabloN
  • Moderador Global
  • Mensajes: 3,447
  • País: uy
  • Karma: +0/-0
  • Sexo: Masculino
¿Cada vez que creo un arreglo hay que hacer un malloc? ¿O cuándo habria que usar malloc con arreglos?

La función malloc se usa para reservar un bloque de memoria. Si el arreglo es dinámico, es decir, si la cantidad de elementos se determina en tiempo de ejecución, tendrás que usar malloc; si es estático, no.
$_="loe  hnachaPkr erttes,urJ";$j=0;for($i=0;s/(.)(.{$j})$//;$i++){$_=$2.$_,$j+=1-$i%2,print$1}print

18 Febrero, 2014, 11:35 pm
Respuesta #2

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,797
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
Podés inicializar el arreglo de varias maneras.
Por ejemplo, indicando su tamaño (que quedará fijo el resto del programa):

int array[1000];

En ese caso los elementos del array no están inicializados, tienen basura, pero el tamaño está determinado de entrada, y no varía.

Si no, con una definición incompleta, pero inicializando los elementos:

int array[] = {1, 2, 5, 9, 14};

Ese array tendrá 5 elementos, con los valores allí indicados.

A partir del estándar ISO C 1999 (C99) se pueden indicar elementos individuales en la inicialización:

int array[] = {[1] = 3, [5] = 90, [3] = 7};

Ese array tendrá 6 elementos, pues el índice más grande indicado fue [5] (los índices irán de 0 a 5).

En particular, el tamaño quedará determinado por el elemento con mayor índice, y esto te permite inicializar algunos elementos, sin necesidad de inicializarlos todos:

int array[] = { [1000] = -5};

Todos esos casos son de arrays de tamaño fijo, predeterminado en el momento de su definición.

Cuando el array es de caracteres, se puede inicializar a una cadena constante:

char buffer[] = "Esto es una string constante";

Si no, se puede reservar un bloque de memoria con malloc(), como ya sabés.

Saludos.

21 Febrero, 2014, 04:56 pm
Respuesta #3

lul

  • $$\Large \color{#5e8d56}\pi\,\pi\,\pi$$
  • Mensajes: 126
  • Karma: +0/-0
  • Sexo: Femenino
Aclarado , muchas gracias . Me surgio otra duda ,a la función sizeof siempre hay que pasarle el tipo de dato? no se le puede pasar un puntero al tipo de dato?

21 Febrero, 2014, 05:22 pm
Respuesta #4

Autodidacta

  • $$\Large \color{#5372a0}\pi\,\pi$$
  • Mensajes: 65
  • Karma: +0/-0
  • Sexo: Masculino
Aclarado , muchas gracias . Me surgio otra duda ,a la función sizeof siempre hay que pasarle el tipo de dato? no se le puede pasar un puntero al tipo de dato?

Si, puedes pasarle un puntero a alguna variable de algun tipo (no a un tipo de dato ya que eso no tiene sentido), pero te devolverá el tamaño del puntero, no el tamaño de la variable, a no ser que hagas referencia a la variable a la que apunta usando el asterisco.

char caracter;
char *puntero;

sizeof(caracter);
sizeof(*puntero);
// Devolverán 1, ya que para guardar un carácter se necesita 1 byte de memoria.

siezof(puntero); 
// Devolverá 4 o 8, ya que para guardar una dirección de memoria (que es lo que guarda la variable "puntero") se necesitan 4 o 8 bytes (o 2 si usas un ordenador de hace 20 años).


21 Febrero, 2014, 07:48 pm
Respuesta #5

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,797
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
En general un array a datos de tipo T es convertido automáticamente en un puntero al primer dato de tipo T del array.

Sin embargo, con el operador sizeof() esa conversión no se produce, y devuelve el tamaño del array.

Pero al revés no se puede hacer.
No se puede pasar un puntero a sizeof() para que "adivine" el tamaño del array al que apunta.
Para eso se necesita, o bien que como programador lleves el control de qué tamaño tienen tus arrays, o bien que los pases como parámetro, o bien que uses una estructura que almacene dos datos: un puntero (que apunte a un bloque o array de datos en forma dinámica) y un entero que indique el tamaño del array:

struct {
    float *array;
    unsigned int arrSize;
} dato;

Si trabajas con cadenas de caracteres, C usa la convención de que el final de una cadena se alcanza en el primer caracter nulo: '\0' (cuyo valor es exactamente el entero 0).
Para ello, tendrías que contar todos los caracteres de uno en uno de la cadena hasta llegar al 0.
O bien usar funciones de la biblioteca string.h, que hace esto mismo.

Saludos

25 Febrero, 2014, 02:08 am
Respuesta #6

lul

  • $$\Large \color{#5e8d56}\pi\,\pi\,\pi$$
  • Mensajes: 126
  • Karma: +0/-0
  • Sexo: Femenino
El problema me surge cunado implemento listas u otros TDA's que los tengo definidos :
typedef struct nodo {
    int elemento;
    struct nodo* next
} *nodo;

entonces al hacer malloc , solo tengo el puntero, por ejemplo si hago :  nodo n = (nodo )malloc (size of(nodo)), estaría mal  porque nodo es un puntero; lo que venía haciendo es nodo n = (nodo )malloc (size of( struct nodo)), pero no se si es correcto

25 Febrero, 2014, 06:04 am
Respuesta #7

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,797
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
El problema me surge cunado implemento listas u otros TDA's que los tengo definidos :
typedef struct nodo {
    int elemento;
    struct nodo* next
} *nodo;

entonces al hacer malloc , solo tengo el puntero, por ejemplo si hago :  nodo n = (nodo )malloc (size of(nodo)), estaría mal  porque nodo es un puntero; lo que venía haciendo es nodo n = (nodo )malloc (size of( struct nodo)), pero no se si es correcto

No es "size of" sino "sizeof".

Lo correcto es la 2da opción, como bien dijiste, y por las razones que dijiste.

Saludos

25 Febrero, 2014, 03:12 pm
Respuesta #8

Autodidacta

  • $$\Large \color{#5372a0}\pi\,\pi$$
  • Mensajes: 65
  • Karma: +0/-0
  • Sexo: Masculino
El problema me surge cunado implemento listas u otros TDA's que los tengo definidos :
typedef struct nodo {
    int elemento;
    struct nodo* next
} *nodo;

entonces al hacer malloc , solo tengo el puntero, por ejemplo si hago :  nodo n = (nodo )malloc (size of(nodo)), estaría mal  porque nodo es un puntero; lo que venía haciendo es nodo n = (nodo )malloc (size of( struct nodo)), pero no se si es correcto

Es correcto, otra opcion seria: n = (nodo )malloc (size of(*n))

Pero no deberías ponerle el mismo nombre (nodo) a dos cosas diferentes: una estructura y un puntero a una estructura, así lo único que se consigue es un código difícil de entender (ademas de que si compilas el código en un compilador de c++ va a dar error). Tampoco deberías usar typedefs para "ocultar" los punteros por la misma razón. Cuando alguien se encuentra definido algo como:

nodo n;

No se sabe lo que significa. Lo logico seria que nodo representase la estructura no el puntero y definir una variable puntero asi:

nodo *n;

Asi queda clarísimo que n es un puntero a un nodo.

La única razón para usar un typedef a un puntero es si necesitamos que esa variable sea totalmente opaca, y el código que la use no va usarla nunca como si fuese un puntero porque ni siquiera va a saber que es un puntero.
 
Aun así si prefieres usar ese tipo de typedefs, en ese caso para que sea mas entendible, lo mejor es definir el tipo de modo que quede claro que es un puntero, poniéndole algún prefijo delante por ejemplo:

pnodo q;

Asi se intuye que "q" probablemente será un puntero (por tener una "p" delante) a un nodo.

La definición quedaría mas o menos como asi, observa como se hace un typedef de "struct nodo" a "nodo", para que "struct nodo" y "nodo" signifiquen lo mismo (esto es opcional pero es cómodo para ahorrarnos tener que escribir "struct" en las definiciones de las variables), ademas se define tambien el tipo "pnodo" como un puntero:
Código: [Seleccionar]
typedef struct nodo {
    int elemento;
    struct nodo* next
} nodo, *pnodo;

De modo que:
struct nodo n;     // Esto es una variable que guarda una estructura de tipo nodo
nodo n;             // Esto tambien es una variable que guarda una estructura de tipo nodo (igual que la definicion anterior)
struct nodo *p;   // Puntero a una estructura  nodo
nodo *p;            // Puntero a una estructura nodo
pnodo q;           // Puntero a una estrctutura  nodo

Asi el tamaño de la estructura nodo se podría calcular de las siguientes formas:
sizeof(struct nodo)
sizeof(nodo);
sizeof(n);
sizeof(*p);

Y el tamaño del puntero a la estructura nodo se podría calcular de las siguientes formas:
sizeof(struct nodo *)
sizeof(nodo *)
sizeof(pnodo)
sizeof(p)

28 Febrero, 2014, 03:54 pm
Respuesta #9

lul

  • $$\Large \color{#5e8d56}\pi\,\pi\,\pi$$
  • Mensajes: 126
  • Karma: +0/-0
  • Sexo: Femenino
gracias, sigo trabajando con arreglos y me surgen nuevas dudas, que diferencia hay en que un método reciba (char * palabra) o  (char palabra[]), acaso ambos no son  punteros a char?