¿Cómo acceder a una variable local desde una función diferente usando punteros?

¿Puedo tener acceso a una variable local en una función diferente? ¿Si es así, cómo?

void replaceNumberAndPrint(int array[3]) { printf("%i\n", array[1]); printf("%i\n", array[1]); } int * getArray() { int myArray[3] = {4, 65, 23}; return myArray; } int main() { replaceNumberAndPrint(getArray()); } 

El resultado del fragmento de código anterior:

 65 4202656 

¿Qué estoy haciendo mal? ¿Qué significa el “4202656”?

¿Debo copiar toda la matriz en la función replaceNumberAndPrint() para poder acceder a ella más que la primera vez?

myArray es una variable local y, por lo tanto, el puntero solo es válido hasta que se deja el final de su ámbito (que es en este caso la función que contiene getArray ). Si accede más tarde, obtendrá un comportamiento indefinido.

En la práctica, lo que sucede es que la llamada a printf sobrescribe la parte de la stack utilizada por myArray y luego contiene algunos otros datos.

Para corregir su código, debe declarar la matriz en un ámbito que viva lo suficiente (la función main en su ejemplo) o asignarla en el montón. Si lo asigna en el montón, debe liberarlo manualmente o en C ++ usando RAII.

Una alternativa que eché de menos (probablemente incluso la mejor aquí, siempre que la matriz no sea demasiado grande) es envolver su matriz en una estructura y así convertirla en un tipo de valor. Luego devolverlo crea una copia que sobrevive al retorno de la función. Ver la respuesta de tp1 para detalles sobre esto.

No puede acceder a una variable local una vez que se sale del scope. Esto es lo que significa ser una variable local.

Cuando accede a la matriz en la función replaceNumberAndPrint, el resultado no está definido. El hecho de que parece funcionar la primera vez es solo una afortunada coincidencia. Probablemente, la ubicación de la memoria que está señalando no está asignada en la stack y todavía está configurada correctamente para la primera llamada, pero la llamada a printf sobrescribe esto al presionar valores en la stack durante su operación, por lo que la segunda llamada a printf muestra algo diferente.

Necesita almacenar los datos de la matriz en el montón y pasar un puntero, o en una variable que permanece en el scope (por ejemplo, un ámbito global o algo dentro de la función principal).

Prueba algo así. La forma en que lo hace “mata” a myArray causa si está definido localmente.

 #include  #include  void replaceNumberAndPrint(int * array) { printf("%i\n", array[0]); printf("%i\n", array[1]); printf("%i\n" , array[2]); free(array); } int * getArray() { int * myArray = malloc(sizeof(int) * 3); myArray[0] = 4; myArray[1] = 64; myArray[2] = 23; //{4, 65, 23}; return myArray; } int main() { replaceNumberAndPrint(getArray()); } 

Más: http://www.cplusplus.com/reference/clibrary/cstdlib/malloc/

Editar: Como los Comentarios señalaron correctamente: Una mejor manera de hacerlo sería que:

 #include  #include  void replaceNumberAndPrint(int * array) { if(!array) return; printf("%i\n", array[0]); printf("%i\n", array[1]); printf("%i\n" , array[2]); } int * createArray() { int * myArray = malloc(sizeof(int) * 3); if(!myArray) return 0; myArray[0] = 4; myArray[1] = 64; myArray[2] = 23; return myArray; } int main() { int * array = createArray(); if(array) { replaceNumberAndPrint(array); free(array); } return 0; } 

myArray queda fuera del scope apenas sales de getArray. En su lugar, debe asignarle espacio en el montón.

Su código invoca Comportamiento no myArray porque myArray queda fuera del scope tan pronto como getArray() regrese y cualquier bash de utilizar (desreferencia) el puntero colgante es UB.

Las variables locales salen del scope al regresar, por lo que no puede devolver un puntero a una variable local.

Debe asignarlo dinámicamente (en el montón), utilizando malloc o new . Ejemplo:

 int *create_array(void) { int *array = malloc(3 * sizeof(int)); assert(array != NULL); array[0] = 4; array[1] = 65; array[2] = 23; return array; } void destroy_array(int *array) { free(array); } int main(int argc, char **argv) { int *array = create_array(); for (size_t i = 0; i < 3; ++i) printf("%d\n", array[i]); destroy_array(array); return 0; } 

Alternativamente, puede declarar la matriz como estática, teniendo en cuenta que la semántica es diferente. Ejemplo:

 int *get_array(void) { static int array[] = { 4, 65, 23 }; return array; } int main(int argc, char **argv) { int *array = get_array(); for (size_t i = 0; i < 3; ++i) printf("%d\n", array[i]); return 0; } 

Si no sabe qué significa static , lea esta pregunta y respuesta .

La forma correcta de hacerlo es la siguiente:

 struct Arr { int array[3]; }; Arr get_array() { Arr a; a.array[0] = 4; a.array[1] = 65; a.array[2] = 23; return a; } int main(int argc, char **argv) { Arr a = get_array(); for(size_t i=0; i<3; i++) printf("%d\n", a.array[i]); return 0; } 

Para entender por qué necesita hacer esto, necesita saber cómo funciona sizeof (array). C (y, por lo tanto, c ++) se esfuerza por evitar copiar la matriz, y necesita que la estructura lo supere. Por qué se necesita copiar es debido a los ámbitos: el scope de la función get_array () desaparece y cada valor que todavía se necesita de ese ámbito deberá copiarse en el scope de la llamada.

En este código, ha utilizado el puntero a objetos locales, pero cuando una función devuelve todas las variables locales queda fuera del scope. Si va a asignar memoria (usando la función malloc() para la asignación), entonces no se perderán datos ni se sobrescribirán.

 int* getArray(int size) { int *myArray = (int*)malloc(size*sizeof(int)); myArray[0] = 4; myArray[1] = 65; myArray[2] = 23; return myArray; } int main() { int i; int *vector = getArray(3); for(i=0;i<3;i++) { printf("%i\n",vector[i]); } getch(); return 0; } 

Este código imprimirá todos los elementos de la matriz y no se sobrescribirán.

Solución C ++:

“¿Puedo tener acceso a una variable local en una función diferente? En caso afirmativo, ¿cómo?”

La respuesta es no, no después de que la función ha terminado. Las variables locales se destruyen en ese punto.

En C++ la forma de lidiar con la devolución de matrices es administrarlas en un contenedor como std :: array (tamaño fijo) o std :: vector (tamaño dynamic).

P.ej:

 void replaceNumberAndPrint(const std::array& array) { printf("%i\n", array[0]); printf("%i\n", array[1]); printf("%i\n", array[2]); } std::array getArray() { std::array myArray = {4, 65, 23}; return myArray; } 

En la segunda función, el valor devuelto es optimizado por el comstackdor, por lo que no paga el precio de copiar realmente la matriz.