2011-07-04 42 views
47

Escribí una función que contiene una matriz como argumento, y la llamo pasando el valor de la matriz de la siguiente manera.Pasar una matriz como argumento a una función en C

void arraytest(int a[]) 
{ 
    // changed the array a 
    a[0]=a[0]+a[1]; 
    a[1]=a[0]-a[1]; 
    a[0]=a[0]-a[1]; 
} 

void main() 
{ 
    int arr[]={1,2}; 
    printf("%d \t %d",arr[0],arr[1]); 
    arraytest(arr); 
    printf("\n After calling fun arr contains: %d\t %d",arr[0],arr[1]); 
} 

Lo que he encontrado es a pesar de que estoy llamando arraytest() función pasando los valores, se cambia la copia original del int arr[].

¿Puede explicar por qué?

+1

Está pasando la matriz por referencia pero está modificando su contenido; por lo tanto, está viendo un cambio en los datos –

Respuesta

65

Al pasar una matriz como un parámetro, este

void arraytest(int a[]) 

significa exactamente lo mismo que

void arraytest(int *a) 

por lo que son modificar los valores de principal.

Por razones históricas, las matrices no son ciudadanos de primera clase y no pueden pasarse por valor.

+2

¡bien lo entendí! ¡entonces los arrays no son pasados ​​por ningún valor! –

+1

¿Qué notación es mejor bajo qué circunstancias? –

+7

@Ramon - Usaría la segunda opción, ya que parece menos confuso y mejor indica que no se obtiene una copia de la matriz. –

4

Está pasando el valor de la ubicación de memoria del primer miembro de la matriz.

Por lo tanto, cuando comience a modificar la matriz dentro de la función, está modificando la matriz original.

Recuerde que a[1] es *(a+1).

+0

Supongo que faltan() para * a + 1 debe ser * (a + 1) – ShinTakezou

+0

@ Shin Gracias, hace un tiempo desde que jugué con C. – alex

6

No está pasando la matriz como copia. Es solo un puntero que apunta a la dirección donde está el primer elemento en la memoria.

6

Usted está de paso la dirección del primer elemento de la matriz

6

En C, a excepción de algunos casos especiales, una referencia a un array siempre "desintegraciones" a un puntero al primer elemento de la matriz. Por lo tanto, no es posible pasar una matriz "por valor". Una matriz en una llamada de función se pasará a la función como un puntero, que es análogo a pasar la matriz por referencia.

EDIT: Hay tres de estos casos especiales en una matriz no decae a un puntero a su primer elemento:

  1. sizeof a no es lo mismo que sizeof (&a[0]).
  2. &a no es lo mismo que &(&a[0]) (y no exactamente lo mismo que &a[0]).
  3. char b[] = "foo" no es lo mismo que char b[] = &("foo").
+0

Si paso una matriz a una función. Digamos, por ejemplo, que hice una matriz 'int a [10]' y asigné a cada elemento un valor aleatorio. Ahora si paso esta matriz a una función usando 'int y []' o 'int y [10]' o 'int * y'. Y luego en esa función uso' sizeof (y) 'La respuesta será el puntero de bytes ha sido asignado. Entonces, en este caso, decaerá como un puntero. Sería útil si incluye esto también. Vea esto https://postimg.org/image/prhleuezd/ –

+0

Si utilizo 'sizeof' para operar en la función en la matriz originalmente definida, entonces se descompondrá como una matriz, pero si paso en otra función, entonces usará' sizeof' operador decaerá como un puntero. –

+0

https://stackoverflow.com/questions/8269048/length-of-array-in-function-argument?noredirect=1&lq=1 –

2

Si desea pasar una sola dimensión de matriz como un argumento a una función, que tendría que declarar un parámetro formal en una de las siguientes tres maneras y los tres métodos de declaración de producir resultados similares, ya que cada le dice al compilador que se va a recibir un puntero entero.

int func(int arr[], ...){ 
    . 
    . 
    . 
} 

int func(int arr[SIZE], ...){ 
    . 
    . 
    . 
} 

int func(int* arr, ...){ 
    . 
    . 
    . 
} 

Por lo tanto, va a modificar los valores originales.

Gracias !!!

1

matrices en C se convierten, en la mayoría de los casos, a un puntero al primer elemento de la propia matriz. Y más en detalle las matrices pasadas a funciones siempre se convierten en punteros.

aquí una cita de K&R2nd:

Cuando un nombre de matriz se pasa a una función, lo que se pasa es el ubicación del elemento inicial. Dentro de la función llamada, este argumento es una variable local, por lo que un parámetro de nombre de matriz es un puntero , es decir, una variable que contiene una dirección.

Escritura:

void arraytest(int a[]) 

tiene el mismo significado que la escritura:

void arraytest(int *a) 

Así que a pesar de que no está escribiendo explícitamente se lo que está pasando un puntero y por lo que están modificando los valores en el principal.

Para más Realmente sugiero leer this.

Por otra parte, se pueden encontrar otras respuestas en SO here

0

Pasar una matriz multidimensional como argumento de una función. Pasar una matriz tenue como argumento es más o menos trivial. Echemos un vistazo en caso más interesante de pasar una matriz de 2 dim. En C no puede usar un puntero a construcción de puntero (int **) en lugar de 2 dim array. Hagamos un ejemplo:

void assignZeros(int(*arr)[5], const int rows) { 
    for (int i = 0; i < rows; i++) { 
     for (int j = 0; j < 5; j++) { 
      *(*(arr + i) + j) = 0; 
      // or equivalent assignment 
      arr[i][j] = 0; 
     } 
    } 

Aquí he especificado una función que toma como primer argumento un puntero a un array de 5 enteros. puedo pasar como argumento cualquier 2 gama tenue que tiene 5 columnas:

int arr1[1][5] 
int arr1[2][5] 
... 
int arr1[20][5] 
... 

Es posible llegar a una idea de definir una función más general que puede aceptar cualquier 2 gama tenue y cambiar la firma de la función de la siguiente manera:

void assignZeros(int ** arr, const int rows, const int cols) { 
    for (int i = 0; i < rows; i++) { 
     for (int j = 0; j < cols; j++) { 
      *(*(arr + i) + j) = 0; 
     } 
    } 
} 

Este código se compilará, pero usted recibirá un error de ejecución cuando se trata de asignar los valores de la misma manera que en la primera función. Por lo tanto, en C, las matrices multidimensionales no son lo mismo que los punteros a los punteros ... a los punteros. Un int (* arr) [5] es un puntero a una matriz de 5 elementos, y un int (* arr) [6] es un puntero a la matriz de 6 elementos, ¡y son un puntero a diferentes tipos!

Bueno, ¿cómo definir argumentos de funciones para dimensiones más altas? Simple, ¡solo seguimos el patrón! Hier ist la misma función ajustado para tener una matriz de 3 dimensiones:

void assignZeros2(int(*arr)[4][5], const int dim1, const int dim2, const int dim3) { 
    for (int i = 0; i < dim1; i++) { 
     for (int j = 0; j < dim2; j++) { 
      for (int k = 0; k < dim3; k++) { 
       *(*(*(arr + i) + j) + k) = 0; 
       // or equivalent assignment 
       arr[i][j][k] = 0; 
      } 
     } 
    } 
} 

Como era de esperar, se puede tomar como argumento cualquiera de los 3 conjuntos tenues que tienen en la segunda dimensiones 4 elementos y en la tercera dimensión 5 elementos. Algo como esto estaría bien:

arr[1][4][5] 
arr[2][4][5] 
... 
arr[10][4][5] 
... 

Pero tenemos que especificar todas las dimensiones tamaños hasta la primera.

Cuestiones relacionadas