¡Buenas!
Si ya te están pasando el puntero a la zona de memoria que tenés que modificar, no hace falta que la devuelvas y la asignes
#include <stdio.h>
void creaVector(int*);
int main() {
int vec[5];
int k;
creaVector(vec);
for(k=0;k<5;k++)
printf("%i",vec[k]);
return 0;
}
void creaVector(int *vec) {
vec[0]= 2;
vec[1]= 5;
vec[2]= 3;
vec[3]= 0;
vec[4]= 6;
}
Si quisieras usar memoria dinámica, harías algo así:
#include <stdio.h>
#include <stdlib.h>
int *creaVector();
int main() {
int *vec;
int k;
vec = creaVector();
for(k=0;k<5;k++)
printf("%i",vec[k]);
free(vec);
return 0;
}
int *creaVector(void) {
// version prolija de malloc(sizeof(int) * 5)
int *numeros = calloc(5, sizeof(int));
numeros[0]= 2;
numeros[1]= 5;
numeros[2]= 3;
numeros[3]= 0;
numeros[4]= 6;
return numeros;
}
La memoria se reserva con calloc() en este caso en lugar de malloc(), pero en sí es lo mismo. En este caso creaVector() **sí** devuelve el puntero, porque vec no apunta a ningún lado (fijate incluso que ni siquiera se la pasamos a creaVector()).
Básicamente, en este último caso, creaVector() crea un nuevo array con esos datos pre-seteados, mientras que en el caso anterior creaVector() **solamente llena los datos** (la memoria ya se la habían reservado de afuera). Por eso la primer versión necesita un puntero al bloque de memoria en que escribir, mientras que en la nueva no necesita nada (el que quiera pensar en un constructor de Objetos, no es eso, pero la idea no es taaaaaaan distinta).
Por otro lado, fijate que como la memoria la estamos pidiendo nosotros con calloc(), en el segundo caso tenemos que **liberar la memoria** con un free(). En la primer versión, como el array es estático, la memoria la reserva el compilador en la entrada de stack de la función main(). Entonces, esa memoria la va a liberar el mismo compilador, cuando retire del stack el bloquecito de variables que corresponden a la función main() cuando esta finalice. Por eso no le hacemos free() en la primer versión.
"Che, ¿y si quisiera que creaVector() de la segunda versión igualmente reciba el puntero y no devuelva nada?"
Buen, podés hacerlo, pero el puntero no va a ser el mismo que esperamos en la primer versión. En la primer versión, el puntero que recibimos apunta a la zona donde escribir los datos. Nosotros *no modificamos el puntero*, sino su contenido. Recordemos que en C todos los pasajes de parámetros son por valor (es decir, recibimos una copia del valor de la variable con que nos llamaron), entonces las modificacionesque hagamos a nuestros parámetros sólo duran el scope de nuestra función: cuando retornemos a la función que nos llamó, las variables que nos mandaron como parámetros van a estar intactas.
Entonces, el truco es el de siempre: pasar punteros a lo que sea que querramos modificar.
Nos encantaría hacer algo como esto, como primer approach:
#include <stdio.h>
#include <stdlib.h>
void creaVector(int*);
/* WARNING: ESTO NO FUNCIONA */
/* WARNING: ESTO NO FUNCIONA */
/* WARNING: ESTO NO FUNCIONA */
int main() {
int *vec;
int k;
creaVector(vec);
for(k=0;k<5;k++)
printf("%i",vec[k]);
free(vec);
return 0;
}
void creaVector(int *numeros) {
numeros = calloc(5, sizeof(int));
numeros[0]= 2;
numeros[1]= 5;
numeros[2]= 3;
numeros[3]= 0;
numeros[4]= 6;
}
PEEEEEEEERO estaríamos modificando numeros sólo en el contexto de creaVector(), y cuando vuelva la ejecución al main, vec sigue valiendo lo mismo de siempre. La solución es pasarle a creaVector un puntero a vec:
#include <stdio.h>
#include <stdlib.h>
void creaVector(int**);
int main() {
int *vec;
int k;
creaVector(&vec); // & = "la dirección de" = "un puntero a"
for(k=0;k<5;k++)
printf("%i",vec[k]);
free(vec);
return 0;
}
void creaVector(int **numeros) { // ** porque es puntero a puntero a int
*numeros = calloc(5, sizeof(int)); // *numeros = "el contenido de numeros"
(*numeros)[0]= 2;
(*numeros)[1]= 5;
(*numeros)[2]= 3;
(*numeros)[3]= 0;
(*numeros)[4]= 6;
}
Como es una paja escribir tantos (*numero)[?]=?;, hacemos alguna manganeta loca para simplificar las cosas:
void creaVector(int **numeros) {
int *auxiliar = calloc(5, sizeof(int)); // un int* común y silvestre
auxiliar[0]= 2;
auxiliar[1]= 5;
auxiliar[2]= 3;
auxiliar[3]= 0;
auxiliar[4]= 6;
*numeros = auxiliar; // al contenido de numeros le asigno el valor de mi puntero auxiliar
}
Si me preguntan, es más feliz la alternativa de creaVector() sin parámetros (porque, vamos, si él mismo va a reservar la zona de memoria, efectivamente no necesita ningún dato externo para funcionar - ¡¿¿quién dijo encapsulamiento??! ¡Te escuché!).
That's it